1. Phạm vi truy cập trong Java là gì?

Phạm vi truy cập trong Java – Access modifier là việc giúp ta xác định phạm vi truy cập của biến, phương thức class này cho class khác. Và cụ thể ở đây ta sẽ dùng các từ khóa để xác định phạm vi truy cập cho chúng. Sử dụng access modifier giúp kích thích tính đóng gói cho code của bạn. Nghĩa là, với tính đóng gói, ta có thể kiểm soát phần chương trình nào có thể truy cập vào các thành viên của một class . Do đó, có thể ngăn chặn được việc sử dụng nhầm dữ liệu.

Và phạm vi truy cập có 4 kiểu. Hay ta có thể hiểu là ta có 4 từ khóa để làm việc:

  • public : tất cả các class khác trong hay ngoài package và nội bộ class đều có thể truy cập đến các biến, các phương thức public của class này.
  • protected : chỉ những class ở cùng package hoặc những class extends từ class này và nội bộ class mới có thể truy cập đến các biến, phương thức public của class này.
  • default : chỉ những class ở cùng package với class này và nội bộ class thì mới có thể truy cập đến các biến, các phương thức public của class này.
  • private : chỉ những class nằm bên trong class này mới có quyền truy cập đến các biến, phương thức public của class này.

Lưu ý

Trong trường hợp có nhiều class trong cùng 1 package hoặc các package khác nhau thì chúng ta phải tiến hành chạy (run) lớp có hàm main().

2. Phạm vi truy cập Public trong Java

Chắc hẳn các bạn không quá lại gì với từ khóa public . Vì mình đã sử dụng trong rất nhiều những ví dụ ở những bài trước. Vì sao mình lại sử dụng nó nhiều vậy? Vì public là phạm vi truy cập rộng, có thể truy cập bất cứ đâu trong project Java. Một class, method, constructor, interface, … được khai báo public có thể được truy cập từ bất cứ lớp nào khác. Do đó, các trường, phương thức và khối được khai báo bên trong một lớp public có thể được truy cập từ bất kỳ lớp nào trong Java.

Ví dụ:

public class Main {
  public static void main(String[] args) {
    System.out.println("Lập trình từ đầu");
  }
}

Kết quả

Lập trình từ đầu

Lưu ý

Nếu lớp public chúng ta đang cố gắng truy cập là trong một package khác, thì lớp public này vẫn cần được import trước khi truy cập.

2. Phạm vi truy cập Private trong Java

Ngược lại với public thì private lại là access modifer giới hạn quyền truy cập nhiều nhất. Với private thì chúng ta chỉ có thể sử dụng biến, phương thức,… được khai báo với private chỉ có thể truy cập bên trong class được khai báo. Private có phạm vi truy cập mang tính hạn chế nhất. Classinterface không thể là private .

Sử dụng Private Access Modifier trong Java là cách chủ yếu để một đối tượng bao đóng chính nó và ẩn dữ liệu với bên ngoài, giúp an toàn dữ liệu với bên ngoài.

Nhưng nếu ta muốn biến được khai báo private có thể được truy cập bên ngoài lớp nếu như có tạo phương thức public getter cho biến đó tại lớp đó.

Ví dụ:

public class Main {
  private String fname = "Thành";
  private String lname = "Nguyễn";
  private String email = "laptrinhtudau@gmail.com";
  private int age = 19;
  
  public static void main(String[] args) {
    Main myObj = new Main();
    System.out.println("Name: " + myObj.fname + " " + myObj.lname);
    System.out.println("Email: " + myObj.email);
    System.out.println("Age: " + myObj.age);
  }
}

Kết quả

Name: Thành Nguyễn
Email: laptrinhtudau@gmail.com
Age: 19

3. Phạm vi truy cập Protected trong Java

Phạm vi truy cập protected trong Java giúp ta có thể truy cập bên trong package và bên ngoài package nhưng chỉ thông qua tính kế thừa. Các biến, các phương thức được định nghĩa với protected access modifier chỉ có truy cập từ các class nằm trong cùng package và các class con extends từ class này.

Protected không được dùng để khai báo cho classinterface . Các phương thức và thuộc tính của lớp có thể được khai báo protected , tuy nhiên các thuộc tính và phương thức của interface không được khai báo protected .

Ví dụ:

class Person {
  protected String fname = "Thành";
  protected String lname = "Nguyễn";
  protected String email = "laptrinhtudau@gmail.com";
  protected int age = 19;
}

class Student extends Person {
  private int graduationYear = 2022;
  public static void main(String[] args) {
    Student myObj = new Student();
    System.out.println("Name: " + myObj.fname + " " + myObj.lname);
    System.out.println("Email: " + myObj.email);
    System.out.println("Age: " + myObj.age);
    System.out.println("Graduation Year: " + myObj.graduationYear);
  }
}

Kết quả

Name: Thành Nguyễn
Email: laptrinhtudau@gmail.com
Age: 19
Graduation Year: 2022

4. Phạm vi truy cập Default trong Java

Các biến, các phương thức được định nghĩa mà không sử dụng một phạm vi truy cập nào thì nó sẽ được gán phạm vi mặc định là default .

Một biến hoặc phương thức được khai báo mà không có bất kỳ Access Modifier nào là có sẵn cho mọi lớp trong cùng package . Các trường này trong một interface là hoàn toàn public static final và các phương thức trong một interfacepublic theo mặc định.

Ví dụ:

class Person {
  String fname = "Thành";
  String lname = "Nguyễn";
  String email = "laptrinhtudau@gmail.com";
  int age = 19;
  
  public static void main(String[] args) {
    Person myObj = new Person();
    System.out.println("Name: " + myObj.fname + " " + myObj.lname);
    System.out.println("Email: " + myObj.email);
    System.out.println("Age: " + myObj.age);
  }
}

Kết quả

Name: Thành Nguyễn
Email: laptrinhtudau@gmail.com
Age: 19

Chú ý

Với class ta chỉ có thể sử dụng Public hoặc Default

Với thuộc tính, phương thức, hàm tạo,… ta có thể sử dụng một trong 4 phạm vi truy cập trên

5. Access Modifier và tính kế thừa trong Java

Các phương thức được khai báo public trong một lớp cha cũng phải là public trong tất cả lớp con. Các phương thức được khai báo protected trong một lớp cha phải hoặc là protected hoặc public trong các lớp con. Chúng không thể là private . Các phương thức được khai báo mà không có điều khiển truy cập (không sử dụng modifier nào) có thể được khai báo private trong các lớp con. Các phương thức được khai báo private không được kế thừa, do đó không có qui tắc nào cho chúng.

Đối với class ta có thể sử dụng một trong 2 từ khóa

  • Final : Class không thể được kế thừa bởi các Class khác (sẽ được học kế thừa trong bài sau)
final class Vehicle {
  protected String brand = "Ford";
  public void honk() {
    System.out.println("Tuut, tuut!");
  }
}

class Main extends Vehicle {
  private String modelName = "Mustang";
  public static void main(String[] args) {
    Main myFastCar = new Main();
    myFastCar.honk();
    System.out.println(myFastCar.brand + " " + myFastCar.modelName);
  }
}

Kết quả : một lỗi được hiển thị ra

  • abstract : Class không thể được sử dụng để tạo các đối tượng (Để truy cập một lớp trừu tượng, nó phải được kế thừa từ một lớp khác. Ta sẽ tìm hiểu thêm về kế thừa và trừu tượng trong bài sau)

Ví dụ : file main.java

// abstract class
abstract class Main {
  public String fname = "Thành";
  public String lname = "Nguyễn";
  public String email = "laptrinhtudau@gmail.com";
  public int age = 24;
  public abstract void study(); // abstract method 
}

// Subclass (kế thừa từ Person)
class Student extends Main {
  public int graduationYear = 2022;
  public void study() {
    System.out.println("Học cả ngày");
  }
}

Đây là file second.java

class Second {
  public static void main(String[] args) {
// tạo một đối tượng của lớp Student (kế thừa các thuộc tính và phương thức từ Main)
    Student myObj = new Student(); 
    
    System.out.println("Name: " + myObj.fname + " " + myObj.lname);
    System.out.println("Email: " + myObj.email);
    System.out.println("Age: " + myObj.age);
    System.out.println("Graduation Year: " + myObj.graduationYear);
    myObj.study(); // gọi abstract method
  }
}

Kết quả

Name: Thành Nguyễn
Email: laptrinhtudau@gmail.com
Age: 24
Graduation Year: 2022
Học cả ngày