2009-08-03 73 views
2

有一個抽象類:如何改變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

回答

20

你需要getClass().getSuperclass()得到超,不super.getClass()

但是,我真的不建議這樣做。你基本上破壞了抽象類的封裝。如果抽象類沒有爲其後代提供足夠的靈活性,它應該是固定的 - 繞過它只是要求麻煩。如果這個抽象類的其他成員需要更改,會怎樣呢?擁有私有國家的整個目的是讓班級能夠保護自己的數據。使用像這樣的反射是一個非常醜陋的黑客應該是一個絕對的最後度假勝地。

0

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繼承

+0

修好了,謝謝 – 2009-08-03 14:01:40

2

我與喬恩斯基特。從長遠來看,將超類的源代碼更改爲使此字段受保護或將突變委派給可覆蓋的方法會更容易。使用反射來改變這個值現在可以正常工作,但是隨着時間的推移,它不能很好地擴展。