プライベートフィールドを持つクラス

皆さんはフィールド アクセス修飾子についてよく知っています。また、フィールドにprivate修飾子がある場合、外部からアクセスすることはできません。


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

Mainクラスでアクセシビリティを確認してみましょう。


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

にアクセスできませんフィールドですが、反省はあります。:) そして、その助けを借りて、プライベートフィールドにアクセスして操作することができます。

リフレクションを使用してオブジェクトからプライベート フィールドを取得する

getDeclaredFields()メソッドを使用して、クラス内のすべてのフィールドの配列を取得しましょう。これは、操作および変更できるFieldオブジェクトを返します。


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;
    }
プライベート年齢
公開ニックネーム

getFieldNamesメソッドでは、クラスから 2 つのフィールドを取得します。getModifiers メソッドはフィールドの修飾子を返し、getName はフィールドの名前を返します。次に、このフィールドを変更してアクセスしてみましょう。まず、パブリック フィールドからデータを取得してみます。


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);
}
コードジム
コードジム

リフレクションとオブジェクトへの参照の両方を使用してフィールドにアクセスできます。すべてが素晴らしいです!プライベートフィールドに移りましょう。

リクエストされたフィールドの名前をプライベートに変更します分野:


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

作成されたオブジェクトからはアクセスできないため、リフレクションを使用してみてください。エラーが発生します:

不正アクセス例外

IllegalAccessExceptionが発生します。中身を覗いてみましょう:

それを理解してみましょう。

IllegalAccessException はアプリケーションがリフレクティブにインスタンス (配列以外) を作成したり、フィールドを設定または取得したり、メソッドを呼び出したりしようとしたときに、現在実行中のメソッドが指定されたクラス、フィールド、またはメソッドの定義にアクセスできないときにスローされます。メソッド、またはコンストラクター。

ここのメソッドもこの例外をスローします。この例外を回避するために、特別なメソッドを使用してプライベート フィールドにアクセスします。

setAccessible(ブール値フラグ)

このメソッドを使用すると、フィールドまたはクラスのセキュリティ アクセス チェックを回避できます。trueまたは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);

    int age = (int) field.get(person);
    System.out.println("The current value is " + age);
}

結果を見てみましょう:

現在の値は 10 です

素晴らしい!私たちのクラスに関する情報を入手しました。新しい値を割り当ててフィールドを変更してみましょう。


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

フィールドを変更すると、次のようになります。

現在の値は 19 です

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

アクセシビリティをfalseに復元した後、 getメソッドを呼び出そうとすると、再び例外が発生します。

したがって、プライベートフィールドを操作するときは注意してください。また、リフレクションは非常に強力なツールであることを忘れないでください。