Klasse met een eigen veld

Jullie weten allemaal heel goed over modifiers voor veldtoegang. En als een veld de private modifier heeft, dan hebben we er geen toegang van buitenaf toe.


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

Laten we de toegankelijkheid in onze hoofdklasse controleren :


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

We hebben geen toegang tot deleeftijdveld, maar we hebben wel reflectie. :) En met zijn hulp kunnen we toegang krijgen tot en werken met privévelden.

Een privéveld krijgen van een object met behulp van reflectie

Laten we een array krijgen van alle velden in onze klasse met behulp van de methode getDeclaredFields() . Het retourneert een Field- object waarmee we kunnen werken en wijzigen:


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;
    }
privé leeftijd
openbare bijnaam

In de methode getFieldNames krijgen we twee velden van onze klasse. De methode getModifiers retourneert de modifier van ons veld en getName retourneert de naam. Laten we nu proberen dit veld te wijzigen en te openen. Laten we eerst proberen gegevens uit een openbaar veld te halen:


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

We hebben toegang tot het veld zowel met behulp van reflectie als met behulp van onze verwijzing naar het object. Alles is geweldig! Laten we verder gaan naar een privéveld.

We zullen de naam van het gevraagde veld veranderen in onze privateleeftijdveld:


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

We hebben geen toegang via het gemaakte object, dus probeer reflectie te gebruiken. We krijgen een foutmelding:

IllegalAccessException

We krijgen een IllegalAccessException . Laten we eens kijken wat erin zit:

Laten we proberen het uit te zoeken.

Er wordt een IllegalAccessException gegenereerd wanneer een toepassing probeert om reflectief een instantie (anders dan een array) te maken, een veld in te stellen of op te halen, of een methode aan te roepen, wanneer de momenteel uitgevoerde methode geen toegang heeft tot de definitie van de opgegeven klasse, veld, methode of constructeur.

De methoden hier genereren ook deze uitzondering. Om deze uitzondering te voorkomen, gebruiken we een speciale methode om toegang te krijgen tot het privéveld.

setAccessible(booleaanse vlag)

Deze methode maakt het mogelijk om beveiligingstoegangscontroles voor een veld of klasse te vermijden. We kunnen waar of onwaar doorgeven aan de methode om te bepalen of beveiligingstoegangscontroles voor het veld zullen worden uitgevoerd. Laten we proberen onze code te repareren:


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

Laten we eens kijken naar het resultaat:

De huidige waarde is 10

Geweldig! We kregen informatie over onze klas. Laten we ook proberen ons veld te veranderen door er een nieuwe waarde aan toe te wijzen:


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

Nadat we ons veld hebben gewijzigd, krijgen we:

De huidige waarde is 19

Laten we proberen setAccessible(false) aan te roepen .


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

Nadat we de toegankelijkheid hebben hersteld naar false , komen we onze uitzondering opnieuw tegen wanneer we de methode get proberen aan te roepen:

Wees dus voorzichtig bij het werken met privévelden en vergeet niet dat reflectie een zeer krachtig hulpmiddel is!