Kelas dengan medan peribadi

Anda semua tahu betul tentang pengubah akses medan. Dan jika medan mempunyai pengubah suai peribadi , maka kami tidak boleh 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 semak kebolehaksesan dalam kelas Utama kami :


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 mempunyai akses kepadaumurlapangan, tetapi kita mempunyai refleksi. :) Dan dengan bantuannya, kami boleh mengakses dan bekerja dengan bidang persendirian.

Mendapatkan medan peribadi daripada objek menggunakan pantulan

Mari dapatkan tatasusunan semua medan dalam kelas kami menggunakan kaedah getDeclaredFields() . Ia mengembalikan objek Field yang boleh kita bekerjasama dan ubah suai:


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 awam umur peribadi

Dalam kaedah getFieldNames , kami mendapat dua medan daripada kelas kami. Kaedah getModifiers mengembalikan pengubah suai medan kami dan getName mengembalikan namanya. Sekarang mari cuba ubah suai dan akses medan ini. Mula-mula, mari cuba dapatkan data daripada medan awam:


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

Kita boleh mengakses medan kedua-duanya dengan bantuan refleksi dan menggunakan rujukan kita kepada objek. Semuanya bagus! Mari kita beralih ke bidang peribadi.

Kami akan menukar nama medan yang diminta kepada peribadi kamiumurbidang:


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 mempunyai akses melalui objek yang dibuat, jadi cuba gunakan refleksi. Kami mendapat ralat:

IllegalAccessException

Kami mendapat IllegalAccessException . Mari kita lihat apa yang ada di dalamnya:

Mari cuba fikirkan.

IllegalAccessException dilemparkan apabila aplikasi cuba membuat contoh secara reflektif (selain tatasusunan) , menetapkan atau mendapatkan medan, atau menggunakan kaedah, apabila kaedah yang sedang dilaksanakan tidak mempunyai akses kepada definisi kelas, medan, kaedah, atau pembina.

Kaedah di sini juga membuang pengecualian ini. Untuk mengelakkan pengecualian ini, kami akan menggunakan kaedah khas untuk mengakses medan peribadi.

setAccessible(bendera boolean)

Kaedah ini memungkinkan untuk mengelakkan semakan akses keselamatan untuk medan atau kelas. Kami boleh menghantar benar atau salah kepada kaedah untuk menentukan sama ada semakan akses keselamatan akan dilakukan untuk medan tersebut. Mari cuba betulkan kod kami:


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 lihat hasilnya:

Nilai semasa ialah 10

Hebat! Kami mendapat maklumat tentang kelas kami. Mari cuba juga menukar medan kami dengan memberikan nilai baharu kepadanya:


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

Selepas menukar bidang kami, kami mendapat:

Nilai semasa ialah 19

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

Selepas memulihkan kebolehaksesan kepada false , kami menghadapi pengecualian kami sekali lagi apabila kami cuba memanggil kaedah get :

Jadi berhati-hati apabila bekerja dengan bidang persendirian , dan jangan lupa bahawa refleksi adalah alat yang sangat berkuasa!