คลาสที่มีสนามส่วนตัว

ทุกท่านทราบดีเกี่ยวกับตัวดัดแปลงการเข้าถึงฟิลด์ และถ้าฟิลด์มี การปรับเปลี่ยน ส่วนตัวเราก็ไม่สามารถเข้าถึงได้จากภายนอก


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

ตรวจสอบการช่วยสำหรับการเข้าถึงใน ชั้นเรียน หลัก ของเรา :


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

เราไม่มีสิทธิ์เข้าถึงอายุสนาม แต่เรามีการสะท้อนกลับ :) และด้วยความช่วยเหลือ เราสามารถเข้าถึงและทำงานกับฟิลด์ส่วนตัวได้

รับฟิลด์ส่วนตัวจากวัตถุโดยใช้การสะท้อน

มารับอาร์เรย์ของฟิลด์ทั้งหมดในคลาสของเราโดยใช้เมธอดgetDeclaredFields() มันส่งคืน วัตถุ ฟิลด์ที่เราสามารถทำงานและแก้ไขได้:


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

ชื่อเล่นสาธารณะอายุส่วนตัว

ใน เมธอด getFieldNamesเราได้รับสองฟิลด์จากคลาสของเรา เมธอด getModifiers จะส่งคืนตัวแก้ไขฟิลด์ของเรา และgetNameจะส่งคืนชื่อของมัน ตอนนี้ลองแก้ไขและเข้าถึงฟิลด์นี้ ขั้นแรก ลองรับข้อมูลจากสนามสาธารณะ:


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);
}
โค้ดยิม
โค้ดยิม

เราสามารถเข้าถึงฟิลด์ได้โดยใช้การสะท้อนกลับและใช้การอ้างอิงถึงวัตถุ ทุกอย่างยอดเยี่ยม! ไปที่สนามส่วนตัวกันเถอะ

เราจะเปลี่ยนชื่อฟิลด์ที่ขอเป็นส่วนตัวของเราอายุสนาม:


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

เราไม่สามารถเข้าถึงได้ผ่านวัตถุที่สร้างขึ้น ดังนั้นลองใช้การสะท้อนกลับ เราได้รับข้อผิดพลาด:

การเข้าถึงข้อยกเว้นที่ผิดกฎหมาย

เราได้รับIllegalAccessException มาดูกันดีกว่าว่ามีอะไรอยู่ข้างในบ้าง:

ลองคิดดูสิ

ข้อ ผิดพลาด IllegalAccessExceptionเกิดขึ้นเมื่อแอปพลิเคชันพยายามสร้างอินสแตนซ์แบบไตร่ตรอง (นอกเหนือจากอาร์เรย์) ตั้งค่าหรือรับฟิลด์ หรือเรียกใช้เมธอด เมื่อเมธอดที่กำลังดำเนินการอยู่ไม่สามารถเข้าถึงคำจำกัดความของคลาส ฟิลด์ ที่ระบุ วิธีการหรือตัวสร้าง

วิธีการที่นี่ยังโยนข้อยกเว้นนี้ เพื่อหลีกเลี่ยงข้อยกเว้นนี้ เราจะใช้วิธีพิเศษในการเข้าถึงฟิลด์ส่วนตัว

setAccessible (ธงบูลีน)

วิธีนี้ทำให้สามารถหลีกเลี่ยงการตรวจสอบการเข้าถึงความปลอดภัยสำหรับฟิลด์หรือคลาสได้ เราสามารถส่งผ่านจริงหรือเท็จไปยังเมธอดเพื่อกำหนดว่าจะตรวจสอบการเข้าถึงความปลอดภัยสำหรับฟิลด์นั้นหรือไม่ ลองแก้ไขรหัสของเรา:


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

ลองดูผลลัพธ์:

ค่าปัจจุบันคือ 10

ยอดเยี่ยม! เราได้ข้อมูลเกี่ยวกับชั้นเรียนของเรา ลองเปลี่ยนฟิลด์ของเราด้วยการกำหนดค่าใหม่ให้:


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

หลังจากเปลี่ยนฟิลด์ เราได้รับ:

มูลค่าปัจจุบันคือ 19

มาลองเรียก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));
}

หลังจากกู้คืนการเข้าถึงเป็นfalseเราพบข้อยกเว้นอีกครั้งเมื่อเราพยายามเรียกใช้ เมธอด get :

ดังนั้นควรระมัดระวังเมื่อทำงานกับ พื้นที่ ส่วนตัวและอย่าลืมว่าการไตร่ตรองเป็นเครื่องมือที่ทรงพลังมาก!