Classe con un campo privato
Conoscete tutti molto bene i modificatori di accesso al campo. E se un campo ha il modificatore privato , non possiamo accedervi dall'esterno.
public class Person {
private int age;
public String nickname;
public Person(int age, String nickname) {
this.age = age;
this.nickname = nickname;
}
}
Controlliamo l'accessibilità nella nostra classe principale :
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
}
}
Non abbiamo accesso aletàcampo, ma abbiamo la riflessione. :) E con il suo aiuto, possiamo accedere e lavorare con campi privati.
Ottenere un campo privato da un oggetto usando la riflessione
Prendiamo un array di tutti i campi nella nostra classe usando il metodo getDeclaredFields() . Restituisce un oggetto Field con cui possiamo lavorare e modificare:
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;
}
soprannome pubblico dell'età privata
Nel metodo getFieldNames , otteniamo due campi dalla nostra classe. Il metodo getModifiers restituisce il modificatore del nostro campo e getName restituisce il suo nome. Ora proviamo a modificare ed accedere a questo campo. Innanzitutto, proviamo a ottenere dati da un campo pubblico:
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
Possiamo accedere al campo sia con l'aiuto della riflessione sia usando il nostro riferimento all'oggetto. È tutto bellissimo! Passiamo a un campo privato.
Cambieremo il nome del campo richiesto in privatoetàcampo:
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);
}
Non abbiamo accesso tramite l'oggetto creato, quindi prova a utilizzare la riflessione. Otteniamo un errore:

IllegalAccessException
Otteniamo un IllegalAccessException . Diamo un'occhiata a cosa c'è dentro:

Proviamo a capirlo.
Un'eccezione IllegalAccessException viene generata quando un'applicazione tenta di creare in modo riflessivo un'istanza (diversa da un array), impostare o ottenere un campo o richiamare un metodo, quando il metodo attualmente in esecuzione non ha accesso alla definizione della classe specificata, campo, metodo o costruttore.
Anche i metodi qui generano questa eccezione. Per evitare questa eccezione, utilizzeremo un metodo speciale per accedere al campo privato.
setAccessibile(flag booleano)
Questo metodo consente di evitare i controlli di accesso di sicurezza per un campo o una classe. Possiamo passare true o false al metodo per determinare se verranno eseguiti i controlli di accesso di sicurezza per il campo. Proviamo a correggere il nostro codice:
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);
}
Diamo un'occhiata al risultato:
Grande! Abbiamo informazioni sulla nostra classe. Proviamo anche a modificare il nostro campo assegnandogli un nuovo valore:
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);
}
Dopo aver modificato il nostro campo, otteniamo:
Proviamo a chiamare 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));
}
Dopo aver ripristinato l'accessibilità a false , ci imbattiamo nuovamente nella nostra eccezione quando proviamo a chiamare il metodo get :

Quindi fai attenzione quando lavori con campi privati e non dimenticare che la riflessione è uno strumento molto potente!
GO TO FULL VERSION