質問

抽象クラスがあります:

public abstract class AbstractAny {
  private long period;

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

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

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

をスローします
役に立ちましたか?

解決

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

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

他のヒント

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

ConcreteSomeは抽象クラスAbstractAnyを拡張していません。
これを試してください

public class ConcreteSome {
    @Override
    public void doSomething() {
        Class<?> clazz = getClass().getSuperclass();
        System.out.println(clazz);
        Field p = clazz.getDeclaredField("period");
        ...

java.lang.Objectを返す必要があります

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top