2

私には2つのクラスがあります:

public abstract class AbstractTestClass {
    private String abstractString = "abstract";
    public void showFields() throws IllegalAccessException{
        for (Field field : this.getClass().getDeclaredFields()) {
            System.out.println(field.get(this));
        }
    }
}

public class TestClass extends AbstractTestClass {
    private String concreteString = "concreteString";
}

そしてテスト:

public class MainTest {
    public static void main(String[] args) throws IllegalAccessException{
        TestClass test = new TestClass();
        test.showFields();
    }
}

このテストを実行すると、次の例外が発生します。

java.lang.IllegalAccessException: Class AbstractTestClass can not access a member of class TestClass with modifiers "private"

コードをデバッグしているとき、これにはTestClassのインスタンスが含まれています。

質問:

  1. なぜそれが起こるのですか?
  2. Field.setAccessible()を使用したり、ファイルの可視性を変更したりせずに、このコードを機能させるにはどうすればよいですか?
4

2 に答える 2

0

Field.setAccessible() を使用したり、フィールドの可視性を変更したりせずに、このコードを機能させるにはどうすればよいですか?

できません。フィールドを使用するには、フィールドをアクセス可能にする必要があります

于 2012-06-08T15:56:26.290 に答える
0

私が始めたときに犯したのと同じ間違いを犯していると思います.抽象クラスと拡張クラスが2つの部分を溶接して、他のすべてのフィールドやメソッドなどにアクセスできる単一のクラスを形成しています.

悲しいことに、これは正しくありません。継承は、通常の親子オブジェクトにおけるより密接な関係ですが、アクセス規則には依然として従う必要があります。たとえば、メソッドがprotected抽象クラスで宣言され、拡張クラスが別のパッケージにある場合、アクセスできません (逆も同様です)。

メソッドshowFields()は で定義されているため、AbstractTestClassそのクラスのフィールドにのみアクセスできます。のフィールドTestClassは基本的に壁で囲まれています。

私が考えることができる唯一の回避策は、 でオーバーライドshowFields()TestClass、プライベート フィールドにアクセスできないという例外をすべて飲み込み、その後super.showFields()、例外を呼び出して再度飲み込むことです。かわいくない。

public abstract class AbstractTest {
  private String abstractString = "abstract";
  public void showFields() throws IllegalAccessException {
    for (Field field : this.getClass().getSuperclass().getDeclaredFields()) {
      try {
        System.out.println(field.get(this));
      }
      catch (IllegalAccessException e) { 
        // swallow 
      }
    }
  }
}

public class MyTest extends AbstractTest
{
  private String concreteString = "concreteString";
  @Override public void showFields() throws IllegalAccessException {
    for (Field field : this.getClass().getDeclaredFields()) {
      try {
        System.out.println(field.get(this));
      }
      catch (IllegalAccessException e) {  
        // swallow
      }
    }
    super.showFields();
  }
}

これはあなたが考えていたことだと思います...

于 2012-06-08T19:29:24.313 に答える