java - 如何修复 "Constructor Calls Overridable Method"

标签 java constructor overriding

我有以下设置,它给我一条消息,指出“构造函数调用可覆盖方法”。我知道会发生这种情况,但我的问题是如何修复它以便代码仍然有效并且消息消失。

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
  }
}

谢谢!

最佳答案

As @Voo says,

your question is about calling a virtual method on an already completely constructed object. The well known downfalls of calling virtual methods on the to constructed object are well known, but don't apply here

来自 Effective Java 2nd Edition , 第十七项:继承的设计和文件,否则禁止:

There are a few more restrictions that a class must obey to allow inheritance. Constructors must not invoke overridable methods, directly or indirectly. If you violate this rule, program failure will result. The superclass constructor runs before the subclass constructor, so the overriding method in the subclass will be invoked before the subclass constructor has run. If the overriding method depends on any initialization performed by the subclass constructor, the method will not behave as expected.

在对象构造期间调用可重写的方法可能会导致使用未初始化的数据,从而导致运行时异常或意外结果。

构造函数必须只调用最终或私有(private)的方法

您可以使用静态工厂方法来解决必须从 Bar 类 创建对象的问题。

Effective Java,第 1 条:考虑静态工厂方法而不是构造函数

The normal way for a class to allow a client to obtain an instance of itself is to provide a public constructor. There is another technique that should be a part of every programmer’s toolkit. A class can provide a public static factory method, which is simply a static method that returns an instance of the class.

因此,您将拥有界面:

public interface Foo {
     void doFoo();
}

和实现:

public class FooImpl implements Foo {
   @Override
   public void doFoo() {
   //.. Do important code
   }
}

要使用您的工厂方法创建您的类,您可以通过以下方式工作:

  • 使用接口(interface)定义类的变量 private Foo fi 而不是 private FooImpl fi,在具体类型上使用接口(interface)是良好封装的关键以及松散耦合您的代码。

  • 将您的默认构造函数设为私有(private),以防止在外部实例化您的类。

    私有(private)酒吧(){ //防止实例化

  • 删除所有对构造函数中存在的方法的覆盖调用。

  • 创建静态工厂方法

最后你得到了一个类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;
    }
}

我的老板说:“声纳警告是关于症状,而不是疾病。能治好病就好了。” !

关于java - 如何修复 "Constructor Calls Overridable Method",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10337011/

相关文章:

java - 如何在选中复选框时进行全屏 Activity

第二个派生类中的 C++ 初始化列表

java - super() 构造函数中的初始化问题

c# - 为什么 Dictionary.ContainsKey() 和 ToString() 会导致 GC Alloc?

templates - Magento 扩展需要覆盖模板

java - bintray api如何授权

java - 线程 “main”中的异常java.lang.ClassNotFoundException:orienit.hadoop.training.sed

java super 没有按预期工作

java - 减少代码重复

python - 如何使用 [] 作为 python 中命名函数参数的默认值?