use*_*479 13 java constructor overriding
我有以下设置,它给我一条消息,指出"构造函数调用Overridable方法".我知道这种情况正在发生,但我的问题是如何修复它以便代码仍然有效并且消息消失了.
public interface Foo{
void doFoo();
}
public class FooImpl implements Foo{
@Override{
public void doFoo(){
//.. Do important code
}
}
public class Bar{
private FooImpl fi;
public Bar(){
fi = new FooImpl();
fi.doFoo(); // The message complains about this line
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
Jes*_*rce 16
正如@Voo所说,
你的问题是关于在已经完全构造的对象上调用虚方法.在构造对象上调用虚方法的众所周知的缺点是众所周知的,但这里不适用
从Effective Java 2nd Edition,Item 17:继承的设计和文档,或者禁止它:
为了允许继承,类必须遵守一些限制.构造函数不得直接或间接调用可覆盖的方法.如果违反此规则,将导致程序失败.超类构造函数在子类构造函数之前运行,因此在子类构造函数运行之前将调用子类中的重写方法.如果重写方法依赖于子类构造函数执行的任何初始化,则该方法将不会按预期运行.
在对象构造期间调用可覆盖的方法可能导致使用未初始化的数据,从而导致运行时异常或意外结果.
构造函数必须只调用final或private方法
您可以使用静态工厂方法来解决您必须从中创建对象的问题Bar class.
有效的Java,第1项:考虑静态工厂方法而不是构造函数
类允许客户端获取自身实例的常规方法是提供公共构造函数.还有另一种技术应该是每个程序员工具包的一部分.类可以提供公共静态工厂方法,它只是一个返回类实例的静态方法.
所以,你去拥有界面:
public interface Foo {
void doFoo();
}
Run Code Online (Sandbox Code Playgroud)
和实施:
public class FooImpl implements Foo {
@Override
public void doFoo() {
//.. Do important code
}
}
Run Code Online (Sandbox Code Playgroud)
要使用工厂方法创建类,可以通过以下方式工作:
使用接口来定义类的变量private Foo fi而不是private FooImpl fi,使用具体类型的接口是良好封装和松散耦合代码的关键.
使您的默认构造函数为私有,以防止您的类在外部实例化.
private Bar(){//防止实例化}
删除所有调用以覆盖构造函数中存在的方法.
创建静态工厂方法
最后,你得到一个Bar工厂方法的类,如:
public class Bar {
private Foo fi;
private Bar() {// Prevents instantiation
fi = new FooImpl();
}
public static Bar createBar() {
Bar newBar = new Bar();
newBar.fi.doFoo();
return newBar;
}
}
Run Code Online (Sandbox Code Playgroud)
我的老板说:"声纳警告是关于症状,而不是疾病.你最好能治疗这种疾病."!
| 归档时间: |
|
| 查看次数: |
24043 次 |
| 最近记录: |