2

有一个抽象类:

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

4

2 回答 2

20

您需要getClass().getSuperclass()获得超类,而不是super.getClass().

但是,我真的不建议这样做。您基本上是在破坏抽象类的封装。如果抽象类没有为它的后代提供足够的灵活性,它应该被修复——绕过它只是自找麻烦。如果这个抽象类的其他成员需要更改,该怎么办?拥有私有状态的全部意义在于让类能够保护自己的数据。像这样使用反射是一个非常丑陋的黑客,应该是绝对的最后手段。

于 2009-08-03T13:55:37.417 回答
2

我和乔恩斯基特在一起。从长远来看,更改超类的源代码以使该字段受保护或将突变委托给可覆盖的方法会更容易。使用反射来更改值现在可以正常工作,但随着时间的推移,它的扩展性并不好。

于 2009-08-03T13:59:22.843 回答