Lớp là một bản thiết kế
Cho đến giờ, code của bạn nằm trong các phương thức truyền qua lại những giá trị đơn giản. Một lớp (class) cho phép bạn gói dữ liệu liên quan và hành vi xử lý dữ liệu đó vào một kiểu có tên riêng. Lớp là bản thiết kế; những thứ bạn thực sự làm việc cùng là các đối tượng (object) được tạo từ nó.
Một lớp khai báo hai loại thành viên: trường (field, dữ liệu mà mỗi đối tượng giữ) và phương thức (method, những gì mỗi đối tượng làm được).
new Dog() tạo một đối tượng trong bộ nhớ và trả cho bạn một tham chiếu đến nó. d.name và d.bark() truy cập vào đúng đối tượng cụ thể đó.
Mỗi đối tượng có trạng thái riêng
Ý nghĩa của một lớp là bạn có thể tạo ra nhiều đối tượng độc lập, mỗi đối tượng mang giá trị trường riêng. Thay đổi một đối tượng không bao giờ chạm đến đối tượng khác.
rex và bella là hai đối tượng riêng biệt. Mỗi đối tượng có name riêng, nên mỗi lần gọi bark() in ra một giá trị khác nhau. Dữ liệu riêng của từng đối tượng này được gọi là trạng thái instance.
Trường và phương thức phối hợp với nhau
Phương thức bên trong một lớp có thể đọc và cập nhật trực tiếp các trường của chính đối tượng đó, không cần truyền chúng vào làm tham số. Phương thức vốn đã "sống trên" đối tượng mà nó xử lý dữ liệu.
Để ý rằng increment() không nhận đối số nào. Nó làm việc trên trường thuộc về chính Counter mà bạn gọi nó. Đây là điểm khác biệt giữa phương thức của lớp và một phương thức static đứng riêng: phương thức có sẵn một đối tượng ngầm định để thao tác.
Từ khóa this
Bên trong một phương thức, this là tham chiếu đến đối tượng mà phương thức được gọi trên đó. Thường bạn không cần nó: viết count đã có nghĩa là this.count. Nhưng this trở nên cần thiết khi tên tham số trùng với tên trường, điều xảy ra liên tục trong setter và hàm khởi tạo.
Một lỗi phổ biến của người mới học là viết x = x; bên trong move. Câu lệnh đó chỉ gán tham số cho chính nó và để nguyên trường: trình biên dịch không cảnh báo, và đối tượng lặng lẽ giữ giá trị cũ. this.x = x; mới là câu lệnh thực sự cập nhật trường.
Giá trị mặc định của trường và tham chiếu null
Khi bạn tạo một đối tượng, các trường của nó không chứa dữ liệu rác: Java khởi tạo chúng với giá trị mặc định: 0 cho số, false cho boolean, và null cho tham chiếu đối tượng như String. Giá trị mặc định null đó là nguồn gốc của một lỗi crash kinh điển.
u.name là null vì chưa ai gán giá trị cho nó, nên gọi .length() trên nó sẽ ném ra NullPointerException. Hãy luôn gán giá trị có ý nghĩa cho đối tượng trước khi dùng các trường của nó, và đó chính là vấn đề mà hàm khởi tạo giải quyết.
Tổ chức code xoay quanh lớp
Các chương trình thực tế mô hình hóa lĩnh vực của chúng thành các lớp giữ dữ liệu và các thao tác trên dữ liệu đó cùng một chỗ. Ở đây một lớp BankAccount giữ số dư và kiểm soát cách số dư thay đổi:
Dữ liệu (balance) và các quy tắc thay đổi nó (deposit, withdraw) nằm ở một chỗ. Code ở nơi khác yêu cầu tài khoản làm việc thay vì tự động vào các con số của nó, và đó là nền tảng của một thiết kế gọn gàng, dễ bảo trì.
Tiếp theo: hàm khởi tạo
Gán từng trường bằng tay sau new vừa tốn công vừa dễ quên, và như bạn vừa thấy, một trường bị quên sẽ để lại null chờ gây crash. Hàm khởi tạo (constructor) cho phép bạn yêu cầu và khởi tạo các trường của đối tượng ngay lúc nó được tạo, nên một BankAccount không bao giờ tồn tại mà thiếu chủ tài khoản. Đó là nội dung của trang tiếp theo.
Câu hỏi thường gặp
Lớp trong Java là gì?
Lớp (class) là một bản thiết kế định nghĩa dữ liệu (trường) và hành vi (phương thức) mà một loại đối tượng sẽ có. Bản thân lớp chỉ là khuôn mẫu: bạn tạo các đối tượng thật từ nó bằng new. Ví dụ, lớp Dog mô tả rằng mọi con chó đều có name và có thể bark(), còn mỗi new Dog() là một con chó riêng với tên riêng.
Lớp và đối tượng trong Java khác nhau thế nào?
Lớp là định nghĩa; đối tượng là một instance cụ thể được tạo từ định nghĩa đó bằng new. Một lớp Person có thể tạo ra nhiều đối tượng Person, mỗi đối tượng giữ giá trị trường riêng. Hãy hình dung lớp là khuôn cắt bánh còn đối tượng là từng chiếc bánh: thay đổi trường của một đối tượng không bao giờ ảnh hưởng đến đối tượng khác.
Từ khóa this trong lớp Java dùng để làm gì?
this chỉ đến đối tượng hiện tại, tức instance cụ thể đang chạy phương thức. Bạn dùng nó để truy cập các trường của chính đối tượng, nhất là khi tham số trùng tên với trường (this.name = name;). Không có this, phép gán chỉ gán tham số cho chính nó và trường vẫn giữ nguyên.