Klasse med privat felt

Dere vet alle veldig godt om felttilgangsmodifikatorer. Og hvis et felt har den private modifikatoren, kan vi ikke få tilgang til det fra utsiden.


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

La oss sjekke tilgjengeligheten i hovedklassen vår :


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 tilgang tilalderfelt, men vi har refleksjon. :) Og med dens hjelp kan vi få tilgang til og jobbe med private felt.

Få et privat felt fra et objekt ved hjelp av refleksjon

La oss få en matrise av alle feltene i klassen vår ved å bruke getDeclaredFields()- metoden. Den returnerer et feltobjekt som vi kan jobbe med og endre:


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
offentlig kallenavn

I getFieldNames- metoden får vi to felt fra klassen vår. GetModifiers-metoden returnerer feltets modifikator, og getName returnerer navnet. La oss nå prøve å endre og få tilgang til dette feltet. Først, la oss prøve å hente data fra et offentlig 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 få tilgang til feltet både ved hjelp av refleksjon og ved å bruke vår referanse til objektet. Alt er flott! La oss gå videre til et privat felt.

Vi endrer navnet på det forespurte feltet til vårt privatealderfelt:


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 tilgang gjennom det opprettede objektet, så prøv å bruke refleksjon. Vi får en feilmelding:

IllegalAccessException

Vi får et IllegalAccessException . La oss ta en titt på hva som er inni:

La oss prøve å finne ut av det.

Et IllegalAccessException blir kastet når en applikasjon forsøker å reflektert lage en forekomst (annet enn en array), sette eller hente et felt, eller påkalle en metode, når metoden som utføres for øyeblikket ikke har tilgang til definisjonen av den spesifiserte klassen, feltet, metode eller konstruktør.

Metodene her kaster også dette unntaket. For å unngå dette unntaket, vil vi bruke en spesiell metode for å få tilgang til det private feltet.

setAccessible (boolsk flagg)

Denne metoden gjør det mulig å unngå sikkerhetskontroller for et felt eller en klasse. Vi kan sende sant eller usant til metoden for å avgjøre om sikkerhetskontroller vil bli utført for feltet. La oss prøve å fikse koden vår:


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

La oss se på resultatet:

Den nåværende verdien er 10

Flott! Vi fikk informasjon om klassen vår. La oss også prøve å endre feltet vårt ved å tilordne det en ny verdi:


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

Etter å ha byttet fagfelt får vi:

Den nåværende verdien er 19

La oss prøve å kalle 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));
}

Etter å ha gjenopprettet tilgjengeligheten til false , støter vi på unntaket vårt igjen når vi prøver å kalle get- metoden:

Så vær forsiktig når du arbeider med private felt, og ikke glem at refleksjon er et veldig kraftig verktøy!