Klasse med privat felt

I kender alle godt til feltadgangsmodifikatorer. Og hvis et felt har den private modifikator, så kan vi ikke få adgang til det udefra.


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

Lad os tjekke tilgængelighed i vores hovedklasse :


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

Vi har ikke adgang tilalderfelt, men vi har refleksion. :) Og med dens hjælp kan vi tilgå og arbejde med private marker.

Få et privat felt fra et objekt ved hjælp af refleksion

Lad os få en matrix af alle felterne i vores klasse ved hjælp af getDeclaredFields() metoden. Det returnerer et feltobjekt , som vi kan arbejde med og ændre:


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;
    }
privat alder
offentligt kaldenavn

I getFieldNames- metoden får vi to felter fra vores klasse. GetModifiers-metoden returnerer vores felts modifikator, og getName returnerer dens navn. Lad os nu prøve at ændre og få adgang til dette felt. Lad os først prøve at hente data fra et offentligt felt:


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

Vi kan tilgå feltet både ved hjælp af refleksion og ved hjælp af vores reference til objektet. Alt er fantastisk! Lad os gå videre til et privat felt.

Vi ændrer navnet på det anmodede felt til vores privatealderMark:


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

Vi har ikke adgang gennem det oprettede objekt, så prøv at bruge refleksion. Vi får en fejl:

IllegalAccessException

Vi får en IllegalAccessException . Lad os tage et kig på, hvad der er indeni:

Lad os prøve at finde ud af det.

En IllegalAccessException udløses, når en applikation forsøger reflekterende at skabe en instans (andre end et array), sætte eller hente et felt eller påkalde en metode, når den aktuelt eksekverende metode ikke har adgang til definitionen af ​​den angivne klasse, felt, metode eller konstruktør.

Metoderne her kaster også denne undtagelse. For at undgå denne undtagelse vil vi bruge en speciel metode til at få adgang til det private felt.

setAccessible(boolesk flag)

Denne metode gør det muligt at undgå sikkerhedsadgangskontrol for et felt eller en klasse. Vi kan videregive sand eller falsk til metoden for at afgøre, om sikkerhedsadgangskontrol vil blive udført for feltet. Lad os prøve at rette vores kode:


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

Lad os se på resultatet:

Den aktuelle værdi er 10

Store! Vi fik information om vores klasse. Lad os også prøve at ændre vores felt ved at tildele det en ny værdi:


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

Efter at have skiftet vores felt får vi:

Den aktuelle værdi er 19

Lad os prøve at kalde 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));
}

Efter at have gendannet tilgængeligheden til false , støder vi på vores undtagelse igen, når vi forsøger at kalde get- metoden:

Så vær forsigtig, når du arbejder med private områder, og glem ikke, at refleksion er et meget kraftfuldt værktøj!