Özel alana sahip sınıf

Alan erişim değiştiricilerini hepiniz çok iyi biliyorsunuz. Ve eğer bir alan özel değiştiriciye sahipse, o zaman ona dışarıdan erişemeyiz.


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

Ana sınıfımızda erişilebilirliği kontrol edelim :


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

şuraya erişimimiz yok:yaşalan, ancak yansımamız var. :) Ve onun yardımıyla özel alanlara erişebilir ve özel alanlarla çalışabiliriz.

yansıma kullanarak bir nesneden özel alan alma

GetDeclaredFields() yöntemini kullanarak sınıfımızdaki tüm alanların bir dizisini elde edelim . Çalışabileceğimiz ve değiştirebileceğimiz bir Field nesnesi döndürür :


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;
    }
özel yaş
genel takma ad

getFieldNames yönteminde sınıfımızdan iki alan alıyoruz. getModifiers yöntemi alanımızın değiştiricisini, getName ise adını döndürür. Şimdi bu alanı değiştirmeyi ve bu alana erişmeyi deneyelim. İlk olarak, ortak bir alandan veri almaya çalışalım:


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

Alana hem yansıma yardımıyla hem de nesneye referansımızı kullanarak erişebiliriz. Her şey harika! Özel bir alana geçelim.

İstenen alanın adını özel olarak değiştireceğizyaşalan:


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

Oluşturulan nesne üzerinden erişimimiz yok, bu yüzden yansımayı kullanmayı deneyin. Bir hata alıyoruz:

Yasa Dışı Erişim İstisnası

Bir IllegalAccessException alıyoruz . Gelin içindekilere bir göz atalım:

Hadi anlamaya çalışalım.

Bir uygulama yansıtıcı olarak bir örnek (dizi dışında) oluşturmaya, bir alanı ayarlamaya veya almaya veya bir yöntemi çağırmaya çalıştığında, o anda yürütülen yöntemin belirtilen sınıf, alan tanımına erişimi olmadığında bir IllegalAccessException atılır . yöntem veya yapıcı.

Buradaki yöntemler de bu istisnayı atar. Bu istisnadan kaçınmak için özel alana erişmek için özel bir yöntem kullanacağız.

setErişilebilir(boole bayrağı)

Bu yöntem, bir alan veya sınıf için güvenlik erişim denetimlerinden kaçınmayı mümkün kılar. Alan için güvenlik erişim kontrollerinin yapılıp yapılmayacağını belirlemek için metoda true veya false geçebiliriz . Kodumuzu düzeltmeye çalışalım:


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

Sonuca bakalım:

Geçerli değer 10'dur

Harika! Sınıfımız hakkında bilgi aldık. Alanımıza yeni bir değer atayarak değiştirmeyi de deneyelim:


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

Alanımızı değiştirdikten sonra şunu elde ederiz:

Geçerli değer 19

setAccessible(false) öğesini çağırmayı deneyelim .


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

Erişilebilirliği false olarak geri yükledikten sonra, get yöntemini çağırmaya çalıştığımızda istisnamızla tekrar karşılaşırız :

Özel alanlarla çalışırken dikkatli olun ve yansıtmanın çok güçlü bir araç olduğunu unutmayın!