Kiểm Soát Quyền Truy Cập (Access Control)
"Trong lập trình hướng đối tượng, Kiểm soát Quyền Truy cập (Access Control) là một tính năng quan trọng trong Java, cho phép bạn xác định các phần tử (biến, phương thức) của một lớp có thể được truy cập từ bên ngoài hoặc từ các lớp khác. Cơ chế này được thực hiện thông qua các Từ khóa Truy cập (Access Modifiers) như private, protected, và public, giúp đảm bảo tính bảo mật và tổ chức mã nguồn hiệu quả. Trong Java, có hai loại điều chỉnh chính: Access Modifiers và Non-access Modifiers."

Trong phần này chúng ta sẽ tìm hiểu về các Access Modifier.
Ⅰ. Access Modifiers (Công cụ sửa đổi truy cập)
Access Modifiers (Công cụ sửa đổi truy cập) trong Java được sử dụng để đặt mức độ truy cập cho các lớp, phương thức, và biến. Java có bốn loại Access Modifiers (Công cụ sửa đổi truy cập) chính:
↳ Public (Công cộng)
↳ Private (Riêng tư)
↳ Protected (Được bảo vệ)
↳ Default (Mặc định hay còn gọi là không có sửa đổi)
Bảng dưới đây mô tả khả năng truy cập của bốn loại Access Modifiers trong java:
Access Modifiers (Công cụ sửa đổi truy cập) | Class (Lớp) | Package (Cùng Gói) | Subclass (Lớp Con khác gói) | World (Toàn Bộ Chương Trình) |
---|---|---|---|---|
Public (Công cộng) | Yes | Yes | Yes | Yes |
Private (Riêng tư) | Yes | No | No | No |
Protected (Được bảo vệ) | Yes | Yes | Yes | No |
Default (Mặc định) | Yes | Yes | No | No |

Bảng mô tả phạm vi áp dụng của từng từ khóa cho các thành phần (lớp,biến, phương thức,constructor) như sau:
Thành phần | Public (Công cộng) | Private (Riêng tư) | Protected (Được bảo vệ) | Default (Mặc định) |
---|---|---|---|---|
Class (Lớp) | Yes | No | No | Yes |
Biến (Variable) | Yes | Yes | Yes | Yes |
Phương thức (Methods) | Yes | Yes | Yes | Yes |
Constructor (Hàm tạo) | Yes | Yes | Yes | Yes |
Ⅱ. Public (Công cộng)
↳ Mức độ truy cập: Không giới hạn. Các thành phần khai báo với public có thể được truy cập từ bất kỳ đâu, từ bất kỳ lớp nào. Public có thể được áp dụng cho lớp, biến, phương thức, constructor.
Ví dụ Code của bạn có hai package và ba class như sau:
Trong Package1: có hai class A và class B
Ví dụ: A.java
// Lưu file với tên A.java
package Package1;
public class A {
public void Display(){
System.out.println("Đây là phương thức của Class A");
}
}
Ví dụ: B.java
// Lưu file với tên B.java
package Package1;
public class B {
public void Display(){
System.out.println("Đây là phương thức của Class B");
}
}
Trong Package2: có một class C
Ví dụ: C.java
// Lưu file với tên C.java
package Package2;
// import Package1.* cho phép bạn sử dụng các lớp từ Package1 trong Package2.
import Package1.*;
public class C {
public static void main(String[] args) {
// Khởi tạo đối tượng của lớp A từ Package1 và gọi phương thức Display
A classa = new A();
classa.Display();
// Khởi tạo đối tượng của lớp B từ Package1 và gọi phương thức Display
B classb = new B();
classb.Display();
}
}
Kết quả của chương trình là:
Đây là phương thức của Class B
Trong ví dụ trên, khi bạn biên dịch và chạy chương trình, Java sẽ bắt đầu thực thi từ phương thức main của lớp C. Nó sẽ tạo ra một đối tượng classa của lớp A và classb của lớp B. Sau đó, nó gọi phương thức Display của cả hai đối tượng này, kết quả là chuỗi trong Phương thức Display sẽ được in ra màn hình.
Ⅲ. Private (Riêng tư)
↳ Mức độ truy cập: chỉ được truy cập trong cùng lớp được khai báo. Các thành phần private không thể được truy cập từ bất kỳ lớp nào khác, ngay cả những lớp kế thừa nó. Private chỉ có thể được áp dụng cho biến, phương thức, constructor. Nó không thể áp dụng cho lớp.
Ví dụ: A.java
package Package1;
public class A {
private int maSV = 11111;
private String hoTen = "VTD";
private double diemSo= 8.5;
private void ThongTin(){
System.out.println("Họ Tên: " + hoTen);
System.out.println("Mã SV: " + maSV);
System.out.println("Điểm Số: " + diemSo);
}
public static void main(String[] args) {
A classa = new A();
System.out.println("Thông tin sinh viên của class A");
classa.ThongTin();
}
}
Kết quả của chương trình là:
Họ Tên: VTD
Mã SV: 11111
Điểm Số: 8.5
Khai báo constructor với từ khóa private
Khi bạn khai báo constructor là private, bạn không thể tạo một đối tượng của lớp đó từ bên ngoài lớp đó. Dưới đây là vi dụ về trường hợp này:
Ví dụ: A.java
package Package1;
// Lớp A
class A {
private int maSV = 11111;
private String hoTen = "VTD";
private double diemSo= 8.5;
// Constructor private Chỉ có thể truy cập từ bên trong lớp A
private A(){
System.out.println("Họ Tên: " + hoTen);
System.out.println("Mã SV: " + maSV);
System.out.println("Điểm Số: " + diemSo);
}
}
// Lớp Bên ngoài (lớp main)
public class main{
public static void main(String[] args) {
System.out.println("Thông tin sinh viên của class A");
A classa = new A();// Lỗi biên dịch
}
}
Kết quả của chương trình là:
Trong trường hợp này, lớp A có một constructor private, điều đó có nghĩa là bạn không thể tạo một đối tượng của lớp A từ lớp main. Vì vậy, chương trình của bạn bị lỗi biên dịch.
Ⅳ. Protected (Được bảo vệ)
↳ Mức độ truy cập: chỉ được truy cập trong cùng một package và kể cả khi ở khác package nhưng phải mối quan hệ kế thừa (extends). Protected có thể được áp dụng cho biến, phương thức, constructor. Nó không thể áp dụng cho lớp.
Ví dụ Code của bạn có hai package và hai class kế thừa như sau:
Trong Package1: có một class A
Ví dụ: A.java
// Lưu file với tên A.java
package Package1;
class A {
protected int maSV = 11111;
protected String hoTen = "VTD";
protected double diemSo= 8.5;
// Constructor protected - Chỉ có thể truy cập từ bên trong lớp A hoặc các lớp con của nó
protected A() {
System.out.println("Họ Tên: " + hoTen);
System.out.println("Mã SV: " + maSV);
System.out.println("Điểm Số: " + diemSo);
}
}
Trong Package2: có một class C kế thừa từ class A
Ví dụ: C.java
// Lưu file với tên C.java
package Package2;
// import Package1.* cho phép bạn sử dụng các lớp từ Package1 trong Package2.
import Package1.*;
public class C extends A {
public static void main(String[] args) {
// Tạo đối tượng của lớp C, điều này sẽ gọi constructor của lớp A thông qua lớp C
C classC = new C();
}
}
Kết quả của chương trình là:
Mã SV: 11111
Điểm Số: 8.5
Trong ví dụ trên, kết quả của chương trình sẽ hiển thị thông tin của sinh viên từ lớp A. Bởi vì C là lớp con của A và các biến, constructor của A có access modifier là protected, nên C có thể gọi constructor của A một cách hợp lệ.
Ⅴ. Default (Mặc định hay còn gọi là không có sửa đổi)
↳ Mức độ truy cập: chỉ được truy cập trong cùng một package. Nếu không khai báo bất kỳ Access Modifier nào, thì thành phần đó sẽ có mức độ truy cập default (package-private). Default có thể được áp dụng cho lớp, biến, phương thức, constructor.
Ví dụ Code của bạn có hai package và ba class như sau:
Trong Package1: có hai class A và class B
Ví dụ: A.java
// Lưu file với tên A.java
package Package1;
// Định nghĩa lớp A
class A {
// Các thuộc tính của lớp A
int maSV;
String hoTen;
double diemSo;
// Constructor của lớp A
A(){
// Constructor này được gọi khi một đối tượng của lớp A được khởi tạo
// Hiển thị thông tin (do các biến chưa được khởi tạo nên giá trị mặc định của chúng sẽ là null hoặc 0)
System.out.println("Họ Tên: " + hoTen);
System.out.println("Mã SV: " + maSV);
System.out.println("Điểm Số: " + diemSo);
}
// Phương thức Thongtin để in ra dấu gạch ngang
void Thongtin(){
System.out.println("-----------");
}
}
Ví dụ: B.java
// Lưu file với tên B.java
package Package1;
// Lớp B để chứa phương thức main để thực thi chương trình
public class B {
public static void main(String[] args) {
// Khởi tạo một đối tượng của lớp A
A classa = new A();
// Gọi phương thức Thongtin() của đối tượng A
classa.Thongtin();
}
}
Kết quả của chương trình là:
Mã SV: 0
Điểm Số: 0.0
-----------
Trong ví dụ trên, kết quả của chương trình sẽ hiển thị thông tin của sinh viên từ lớp A. Bởi vì class A và class B nằm chung trong Package1 và các biến, phương thức, constructor của A có access modifier là default, nên B có thể gọi constructor của A một cách hợp lệ.
Trong Package2: có một class C kế thừa từ class A
Ví dụ: C.java
// Lưu file với tên C.java
package Package2;
import Package1.*;
public class C extends A {
public static void main(String[] args) {
// Khởi tạo một đối tượng của lớp A
A classa = new A();// Xảy ra lỗi biên dịch
}
}
Kết quả của chương trình là:
Trong ví dụ trên, trình biên dịch sẽ bị lỗi khi in thông tin của sinh viên từ lớp A. Bởi vì class A và class C không nằm chung trong Package1 và các biến, phương thức, constructor của A có access modifier là default (chỉ được truy cập trong cùng một package), nên C không có thể gọi constructor của A một cách hợp lệ.