CodeGym /Java tanfolyam / /Objektum belső állapotának megváltoztatása tükröződés se...

Objektum belső állapotának megváltoztatása tükröződés segítségével

Szint , Lecke
Elérhető

Osztály privát mezővel

Mindannyian nagyon jól ismerik a mezőhozzáférés-módosítókat. És ha egy mező rendelkezik a privát módosítóval, akkor azt kívülről nem tudjuk elérni.


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

Vizsgáljuk meg az akadálymentesítést főosztályunkban :


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

Nem férünk hozzá akorterületen, de van reflexiónk. :) Segítségével pedig hozzáférhetünk és dolgozhatunk privát mezőkkel.

Privát mező lekérése egy objektumról tükrözés segítségével

Nézzük meg az osztályunk összes mezőjének tömbjét a getDeclaredFields() metódus segítségével. Egy Field objektumot ad vissza , amellyel dolgozhatunk és módosíthatunk:


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;
    }
magánéleti kor
nyilvános becenév

A getFieldNames metódusban két mezőt kapunk az osztályunkból. A getModifiers metódus visszaadja a mező módosítóját, a getName pedig a nevét. Most próbáljuk meg módosítani és elérni ezt a mezőt. Először próbáljunk meg adatokat szerezni egy nyilvános mezőből:


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

A mezőt reflexió segítségével és az objektumra való hivatkozásunk segítségével is elérhetjük. Minden nagyszerű! Térjünk át egy privát mezőre.

A kért mező nevét privátra változtatjukkorterület:


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

Nincs hozzáférésünk a létrehozott objektumon keresztül, ezért próbálja meg a tükrözést. Hibát kapunk:

IllegalAccessException

IllegalAccessException kivételt kapunk . Vessünk egy pillantást a belsejébe:

Próbáljuk meg kitalálni.

IllegalAccessException kivételt dob, amikor egy alkalmazás megpróbál reflektíven létrehozni egy példányt (nem egy tömböt), beállítani vagy lekérni egy mezőt, vagy meghívni egy metódust, amikor az éppen futó metódus nem fér hozzá a megadott osztály, mező definíciójához, metódus, vagy konstruktor.

Az itteni módszerek is ezt a kivételt vetik ki. A kivétel elkerülése érdekében egy speciális módszert használunk a privát mező eléréséhez.

setAccessible (logikai jelző)

Ez a módszer lehetővé teszi egy mező vagy osztály biztonsági hozzáférés-ellenőrzésének elkerülését. Igaz vagy hamis értéket adhatunk át a metódusnak annak meghatározására, hogy a mező biztonsági hozzáférés-ellenőrzése megtörténik-e. Próbáljuk meg kijavítani a kódunkat:


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

Nézzük az eredményt:

A jelenlegi érték 10

Nagy! Információt kaptunk az osztályunkról. Próbáljuk meg megváltoztatni a mezőnket is úgy, hogy új értéket rendelünk hozzá:


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

A szakterület megváltoztatása után a következőket kapjuk:

A jelenlegi értéke 19

Próbáljuk meg meghívni a setAccessible(false) függvényt .


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

Az akadálymentesítés false értékre való visszaállítása után ismét a kivételünkbe ütközünk, amikor megpróbáljuk meghívni a get metódust:

Legyen tehát óvatos, amikor privát mezőkkel dolgozik , és ne felejtse el, hogy a tükrözés nagyon hatékony eszköz!

Hozzászólások
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION