如何修复“构造函数调用可覆盖的方法”

时间:2012-04-26 15:55:30

标签: java constructor override

我有以下设置,它给我一条消息,指出“构造函数调用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
  }
}

谢谢!

4 个答案:

答案 0 :(得分:16)

  

正如@Voo所说,

     
    

你的问题是关于在已经调用虚拟方法     完全构造的对象。众所周知的呼唤垮台     构造对象上的虚拟方法是众所周知的,但不是     在这里申请

  

来自Effective Java 2nd Edition,第17项:继承的设计和文档,或者禁止它:

  

类必须遵守一些限制以允许   遗产。构造函数不能调用可覆盖的方法,   直接或间接地。如果违反此规则,程序将失败   结果。超类构造函数在子类之前运行   构造函数,因此将调用子类中的重写方法   在子类构造函数运行之前。如果是压倒一切的方法   取决于子类构造函数执行的任何初始化,   该方法不会按预期运行。

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

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

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

有效的Java,第1项:考虑静态工厂方法而不是构造函数

  

允许客户端获取实例的类的常规方法   本身就是提供一个公共构造函数。还有另一种技术   这应该是每个程序员工具包的一部分。一堂课可以   提供一个公共静态工厂方法,它只是一个静态方法   返回类实例的方法。

所以,你去了界面:

public interface Foo {
     void doFoo();
}

和实施:

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

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

  • 使用接口来定义类private Foo fi的变量而不是private FooImpl fi,使用具体类型的接口是良好封装和松散耦合代码的关键。

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

    私人酒吧(){         //防止实例化     }

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

  • 创建静态工厂方法

最后,您将获得一个类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;
    }
}

我的老板说:“声纳警告是关于症状,而不是疾病。你最好能治疗这种疾病。“!

答案 1 :(得分:6)

如果以后不需要覆盖该方法,则可以将doFoo声明为final:

public final void doFoo() { }

答案 2 :(得分:0)

您的IDE告诉您,因为它可能不安全。您可以提供任何implimentation或doFoo,并在启动时将所有Bar对象设置为不同的东西。在大多数情况下,这似乎是一个糟糕的设计选择。

您似乎在构造函数中使用策略模式。在构造函数中使用策略或任何其他可覆盖的行为是不明智的。在其他地方使用它。

答案 3 :(得分:0)

您看到的错误来源是PMD(在那里搜索“overr”),再次构建示例时,此版本的PMD(4.2.6)不会触发此警告。 Sonar只是集成了PMD,Checkstyle和其他工具,并提供了概述。因此,请检查您正在使用的Sonar(和PMD)版本。

您可以在声纳中查看:Sonar > Quality Profiles > Search for "overr"应突出显示您正在使用的规则。

在Sonar中,您可以查看您正在使用的PMD版本。转到Sonar > Configuration > Update Center,然后查看您正在使用的PMD版本。