2

抽象クラスがあります:

public abstract class AbstractAny {
  private long period;

  public void doSomething() {
    // blah blah blah
    period = someHardcodedValue;
    // blah blah blah
  }
}

抽象クラスのソースを変更したくありませんが、フィールド期間の設定方法に柔軟性を追加する必要があります。オーバーライドされたメソッドからフィールド period の値を変更することは可能ですか? たとえば、次のようにします。

public class ConcreteSome extends AbstractAny{
  @Override
  public void doSomething() {
    try {
      Field p = super.getClass().getDeclaredField("period");
      p.setAccessible(true);
      p.setLong(this, 10L);
    } catch (SecurityException e) {
        throw new RuntimeException(e);
    } catch (NoSuchFieldException e) {
        throw new RuntimeException(e);
    } catch (IllegalArgumentException e) {
        throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    }
  }
}

このコードを実行しようとするとsuper.getClass().getDeclaredField("period")スローされますjava.lang.NoSuchFieldException: period

4

2 に答える 2

20

getClass().getSuperclass()ではなく、スーパークラスを取得する必要がありsuper.getClass()ます。

ただし、これを行うことは本当にお勧めしません。基本的に、抽象クラスのカプセル化を破壊しています。抽象クラスがその子孫に十分な柔軟性を提供していない場合は、修正する必要があります。それを回避することは、単に問題を求めているだけです。この抽象クラスの他のメンバーを変更する必要がある場合はどうすればよいでしょうか? プライベートな状態を持つことの要点は、クラスが独自のデータを保護できるようにすることです。このようにリフレクションを使用するのは非常に厄介なハックであり、絶対的な最後の手段にする必要があります。

于 2009-08-03T13:55:37.417 に答える
2

私はジョン・スキートと一緒です。長期的には、スーパークラスのソース コードを変更して、このフィールドを保護するか、変更をオーバーライド可能なメソッドに委譲する方が簡単です。リフレクションを使用して値を変更することは今のところ問題なく機能しますが、時間の経過とともにメンテナンスが行われる限り、うまくスケーリングしません。

于 2009-08-03T13:59:22.843 に答える