คลาสที่มีสนามส่วนตัว
ทุกท่านทราบดีเกี่ยวกับตัวดัดแปลงการเข้าถึงฟิลด์ และถ้าฟิลด์มี การปรับเปลี่ยน ส่วนตัวเราก็ไม่สามารถเข้าถึงได้จากภายนอก
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);
}
ลองดูผลลัพธ์:
ยอดเยี่ยม! เราได้ข้อมูลเกี่ยวกับชั้นเรียนของเรา ลองเปลี่ยนฟิลด์ของเราด้วยการกำหนดค่าใหม่ให้:
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);
}
หลังจากเปลี่ยนฟิลด์ เราได้รับ:
มาลองเรียก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 :

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