CodeGym /Corsi /All lectures for IT purposes /Modifica dello stato interno di un oggetto mediante la ri...

Modifica dello stato interno di un oggetto mediante la riflessione

All lectures for IT purposes
Livello 1, Lezione 82
Disponibile

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

Il valore attuale è 10

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:

Il valore attuale è 19

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!

Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION