如何从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
There's an abstract class:
public abstract class AbstractAny {
private long period;
public void doSomething() {
// blah blah blah
period = someHardcodedValue;
// blah blah blah
}
}
I don't want to change the source of the abstract class but need to add some flexibility on how the field period is being set. Is it possible to change the value of the field period from an overriden method? Like for example:
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);
}
}
}
When I try to run this code super.getClass().getDeclaredField("period")
throws java.lang.NoSuchFieldException: period
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您需要
getClass().getSuperclass()
来获取超类,而不是super.getClass()
。但是,我真的不建议这样做。 您基本上破坏了抽象类的封装。 如果抽象类没有为其后代提供足够的灵活性,则应该对其进行修复 - 绕过它只是自找麻烦。 如果每当这个抽象类的其他成员需要更改时,该怎么办? 拥有私有状态的全部目的是让类能够保护自己的数据。 像这样使用反射是一个非常丑陋的黑客,这应该是绝对的最后手段。
You need
getClass().getSuperclass()
to get the superclass, notsuper.getClass()
.However, I really don't recommend doing this. You're basically destroying the encapsulation of the abstract class. If the abstract class isn't providing enough flexibility for its descendants, it should be fixed - going around it is just asking for trouble. What if some other member of the abstract class needs to be changed whenever this one does? The whole point of having private state is so that the class is able to guard its own data. Using reflection like this is a really ugly hack which should be an absolute last resort.
我和乔恩·斯基特在一起。 从长远来看,更改超类的源代码以保护该字段或将突变委托给可重写的方法会更容易。 使用反射来更改值现在可以正常工作,但随着时间的推移,它的扩展性不太好。
I'm with Jon Skeet. It's easier in the long run to change the superclass's source code to either make this field protected or to delegate mutation to an overridable method. Using reflection to change the value works ok now, but it doesn't scale very well as far as maintenance over time goes.