Lớp có trường riêng

Tất cả các bạn đều biết rất rõ về công cụ sửa đổi truy cập trường. Và nếu một trường có công cụ sửa đổi riêng tư , thì chúng tôi không thể truy cập nó từ bên ngoài.


public class Person {
  private int age;
  public String nickname;
  public Person(int age, String nickname) {
   this.age = age;
   this.nickname = nickname;
  }
}

Hãy kiểm tra khả năng truy cập trong lớp Chính của chúng tôi :


public class Main {
   public static void main(String[] args) {
     Person person = new Person();  
     System.out.println(person.nickname);
    // System.out.println(person.age); No access to the field
  }
}

Chúng tôi không có quyền truy cập vàotuổilĩnh vực, nhưng chúng tôi có sự phản ánh. :) Và với sự trợ giúp của nó, chúng ta có thể truy cập và làm việc với các trường riêng tư.

Nhận một trường riêng tư từ một đối tượng bằng cách sử dụng sự phản chiếu

Hãy lấy một mảng gồm tất cả các trường trong lớp của chúng ta bằng cách sử dụng phương thức getDeclaredFields() . Nó trả về một đối tượng Trường mà chúng ta có thể làm việc và sửa đổi:


public static void main(String[] args) {
        Field[] fields = Person.class.getDeclaredFields();
        List<String> actualFieldNames = getFieldNames(fields);
        actualFieldNames.forEach(System.out::println);
    }

    static List<String> getFieldNames(Field[] fields) {
        List<String> fieldNames = new ArrayList<>();
        for (Field field : fields)
            fieldNames.add(Modifier.toString(field.getModifiers()) + " " + field.getName());
        return fieldNames;
    }

biệt danh công khai tuổi riêng tư

Trong phương thức getFieldNames , chúng ta lấy hai trường từ lớp của mình. Phương thức getModifiers trả về công cụ sửa đổi trường của chúng ta và getName trả về tên của nó. Bây giờ, hãy thử sửa đổi và truy cập vào trường này. Trước tiên, hãy thử lấy dữ liệu từ một trường công khai:


public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    Person person = new Person(10, "CodeGym");

    Field field = Person.class.getDeclaredField("nickname");
    String nickname = (String) field.get(person);
    System.out.println(nickname);

    System.out.println(person.nickname);
}
MãPhòng Tập Thể
DụcMã

Chúng ta có thể truy cập trường với sự trợ giúp của sự phản chiếu và sử dụng tham chiếu của chúng ta đến đối tượng. Mọi thứ đều tuyệt vời! Hãy chuyển sang một lĩnh vực riêng tư.

Chúng tôi sẽ thay đổi tên của trường được yêu cầu thành riêng tư của chúng tôituổicánh đồng:


public static void main(String[]args)throws NoSuchFieldException, IllegalAccessException {
		Person person = new Person(10, "CodeGym");

    Field field = Person.class.getDeclaredField("age");
    int age =(int)field.get(person);
    System.out.println(age);

    // System.out.println(person.age);
}

Chúng tôi không có quyền truy cập thông qua đối tượng đã tạo, vì vậy hãy thử sử dụng sự phản chiếu. Chúng tôi nhận được một lỗi:

Ngoại lệ truy cập bất hợp pháp

Chúng tôi nhận được một IllegalAccessException . Chúng ta hãy xem qua những gì bên trong:

Hãy cố gắng tìm ra nó.

Một IllegalAccessException được ném ra khi một ứng dụng cố gắng tạo một thể hiện (không phải là một mảng), đặt hoặc lấy một trường hoặc gọi một phương thức, khi phương thức đang thực thi không có quyền truy cập vào định nghĩa của lớp, trường đã chỉ định, phương thức hoặc hàm tạo.

Các phương pháp ở đây cũng đưa ra ngoại lệ này. Để tránh ngoại lệ này, chúng tôi sẽ sử dụng một phương thức đặc biệt để truy cập trường riêng tư.

setAccessible(cờ boolean)

Phương pháp này giúp tránh kiểm tra truy cập bảo mật cho một trường hoặc lớp. Chúng ta có thể chuyển true hoặc false cho phương thức để xác định xem việc kiểm tra quyền truy cập bảo mật có được thực hiện cho trường hay không. Hãy thử sửa mã của chúng tôi:


public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    Person person = new Person(10, "CodeGym");

    Field field = Person.class.getDeclaredField("age");
    field.setAccessible(true);

    int age = (int) field.get(person);
    System.out.println("The current value is " + age);
}

Hãy nhìn vào kết quả:

Giá trị hiện tại là 10

Tuyệt vời! Chúng tôi đã nhận được thông tin về lớp học của chúng tôi. Hãy thử thay đổi trường của chúng ta bằng cách gán một giá trị mới cho nó:


public static void main(String[]args)throws NoSuchFieldException, IllegalAccessException {
Person person = new Person(10, "CodeGym");

    Field field = Person.class.getDeclaredField("age");
    field.setAccessible(true);

    field.set(person, 19);

    int age =(int)field.get(person);
    System.out.println("The current value is " + age);
}

Sau khi thay đổi lĩnh vực của chúng tôi, chúng tôi nhận được:

Giá trị hiện tại là 19

Hãy thử gọi setAccessible(false) .


public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    Person person = new Person(10, "CodeGym");

    Field field = Person.class.getDeclaredField("age");
    
    field.setAccessible(true);
    field.set(person, 19);
    field.setAccessible(false);

    System.out.println("The current value is " + field.get(person));
}

Sau khi khôi phục khả năng truy cập thành false , chúng ta lại gặp phải ngoại lệ khi cố gắng gọi phương thức get :

Vì vậy, hãy cẩn thận khi làm việc với các trường riêng tư và đừng quên rằng sự phản chiếu là một công cụ rất mạnh mẽ!