Kelas dengan bidang pribadi

Anda semua tahu betul tentang pengubah akses bidang. Dan jika suatu bidang memiliki pengubah pribadi , maka kita tidak dapat mengaksesnya dari luar.


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

Mari kita periksa aksesibilitas di kelas Utama kita :


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
  }
}

Kami tidak memiliki akses keusialapangan, tapi kami memiliki refleksi. :) Dan dengan bantuannya, kami dapat mengakses dan bekerja dengan bidang pribadi.

Mendapatkan bidang pribadi dari suatu objek menggunakan refleksi

Mari dapatkan array dari semua bidang di kelas kita menggunakan metode getDeclaredFields() . Ini mengembalikan objek Field yang dapat kita kerjakan dan modifikasi:


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;
    }

nama panggilan publik usia pribadi

Dalam metode getFieldNames , kami mendapatkan dua bidang dari kelas kami. Metode getModifiers mengembalikan pengubah bidang kita, dan getName mengembalikan namanya. Sekarang mari kita coba untuk memodifikasi dan mengakses bidang ini. Pertama, mari kita coba mendapatkan data dari bidang publik:


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);
}
CodeGym
CodeGym

Kami dapat mengakses bidang baik dengan bantuan refleksi dan menggunakan referensi kami ke objek. Semuanya bagus! Mari beralih ke bidang pribadi.

Kami akan mengubah nama bidang yang diminta menjadi pribadi kamiusiabidang:


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);
}

Kami tidak memiliki akses melalui objek yang dibuat, jadi coba gunakan refleksi. Kami mendapatkan kesalahan:

IllegalAccessException

Kami mendapatkan IllegalAccessException . Yuk intip isinya :

Mari kita coba mencari tahu.

IllegalAccessException dilontarkan saat aplikasi mencoba membuat instance secara reflektif (selain larik), menyetel atau mendapatkan bidang, atau memanggil metode, saat metode yang saat ini dijalankan tidak memiliki akses ke definisi kelas, bidang, atau metode, atau konstruktor.

Metode di sini juga membuang pengecualian ini. Untuk menghindari pengecualian ini, kami akan menggunakan metode khusus untuk mengakses bidang pribadi.

setAccessible (tanda boolean)

Metode ini memungkinkan untuk menghindari pemeriksaan akses keamanan untuk bidang atau kelas. Kami dapat meneruskan benar atau salah ke metode untuk menentukan apakah pemeriksaan akses keamanan akan dilakukan untuk bidang tersebut. Mari coba perbaiki kode kita:


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);
}

Mari kita lihat hasilnya:

Nilai saat ini adalah 10

Besar! Kami mendapat informasi tentang kelas kami. Mari kita coba juga mengubah bidang kita dengan memberikan nilai baru padanya:


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);
}

Setelah mengubah bidang kami, kami mendapatkan:

Nilai saat ini adalah 19

Mari coba panggil 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));
}

Setelah memulihkan aksesibilitas ke false , kami menemukan pengecualian kami lagi ketika kami mencoba memanggil metode get :

Jadi berhati-hatilah saat bekerja dengan bidang pribadi , dan jangan lupa bahwa refleksi adalah alat yang sangat ampuh!