[英]How to mutate a private field from the abstract class in Java?
有一個抽象類:
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
你需要getClass().getSuperclass()
來獲取超類,而不是super.getClass()
。
但是,我真的不建議這樣做。 你基本上是在破壞抽象類的封裝。 如果抽象類沒有為其后代提供足夠的靈活性,那么它應該是固定的 - 繞過它只是在尋找麻煩。 如果抽象類的其他成員需要在這個時候更改,該怎么辦? 擁有私有狀態的全部意義在於,班級能夠保護自己的數據。 使用像這樣的反射是一個非常丑陋的黑客應該是絕對的最后手段。
我和Jon Skeet在一起。 從長遠來看,更容易將超類的源代碼更改為使該字段受保護或將變異委托給可覆蓋的方法。 使用反射來改變值現在可以正常工作,但是隨着時間的推移,它不能很好地擴展。
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 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.