Klasse mit privatem Feld

Sie alle wissen sehr gut über Feldzugriffsmodifikatoren Bescheid. Und wenn ein Feld den privaten Modifikator hat, können wir von außen nicht darauf zugreifen.


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

Lassen Sie uns die Barrierefreiheit in unserer Hauptklasse überprüfen :


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

Wir haben keinen Zugriff daraufAlterFeld, aber wir haben Reflexion. :) Und mit seiner Hilfe können wir auf private Felder zugreifen und mit ihnen arbeiten.

Abrufen eines privaten Felds von einem Objekt mithilfe von Reflektion

Lassen Sie uns mit der Methode getDeclaredFields() ein Array aller Felder in unserer Klasse abrufen . Es gibt ein Field- Objekt zurück, mit dem wir arbeiten und das wir ändern können:


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;
    }
privater
öffentlicher Spitzname

In der Methode getFieldNames erhalten wir zwei Felder aus unserer Klasse. Die getModifiers-Methode gibt den Modifikator unseres Feldes zurück und getName gibt seinen Namen zurück. Versuchen wir nun, dieses Feld zu ändern und darauf zuzugreifen. Versuchen wir zunächst, Daten aus einem öffentlichen Feld abzurufen:


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

Wir können das Feld sowohl mit Hilfe der Reflexion als auch mit unserem Bezug zum Objekt erschließen. Alles ist ganz toll! Gehen wir weiter zu einem privaten Feld.

Wir ändern den Namen des angeforderten Feldes in „Privat“.AlterFeld:


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

Wir haben über das erstellte Objekt keinen Zugriff, also versuchen Sie es mit Reflektion. Wir erhalten eine Fehlermeldung:

IllegalAccessException

Wir erhalten eine IllegalAccessException . Werfen wir einen Blick auf den Inhalt:

Versuchen wir es herauszufinden.

Eine IllegalAccessException wird ausgelöst, wenn eine Anwendung versucht, reflektiv eine Instanz (außer einem Array) zu erstellen, ein Feld festzulegen oder abzurufen oder eine Methode aufzurufen, wenn die aktuell ausgeführte Methode keinen Zugriff auf die Definition der angegebenen Klasse, des angegebenen Felds hat. Methode oder Konstruktor.

Die Methoden hier lösen auch diese Ausnahme aus. Um diese Ausnahme zu vermeiden, verwenden wir eine spezielle Methode für den Zugriff auf das private Feld.

setAccessible(boolesches Flag)

Diese Methode ermöglicht es, Sicherheitszugriffsprüfungen für ein Feld oder eine Klasse zu vermeiden. Wir können der Methode „true“ oder „false“ übergeben , um zu bestimmen, ob für das Feld Sicherheitszugriffsprüfungen durchgeführt werden. Versuchen wir, unseren Code zu reparieren:


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

Schauen wir uns das Ergebnis an:

Der aktuelle Wert ist 10

Großartig! Wir haben Informationen über unsere Klasse erhalten. Versuchen wir auch, unser Feld zu ändern, indem wir ihm einen neuen Wert zuweisen:


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

Nachdem wir unser Feld geändert haben, erhalten wir:

Der aktuelle Wert beträgt 19

Versuchen wir, setAccessible(false) aufzurufen .


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

Nachdem wir die Zugänglichkeit auf false wiederhergestellt haben, stoßen wir erneut auf unsere Ausnahme, wenn wir versuchen, die get- Methode aufzurufen :

Seien Sie also vorsichtig, wenn Sie mit privaten Feldern arbeiten, und vergessen Sie nicht, dass Reflexion ein sehr mächtiges Werkzeug ist!