2009-08-03 77 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

我与乔恩斯基特。从长远来看,将超类的源代码更改为使此字段受保护或将突变委派给可覆盖的方法会更容易。使用反射来改变这个值现在可以正常工作,但是随着时间的推移,它不能很好地扩展。