为什么java要求第一行构造函数应该调用父构造函数?如果我们绕过这个要求,是否有任何陷阱?

Rom*_*man 3 java constructor

我有下一个代码:

class Foo {

   public Foo (String param) { ... }
}

class Bar extends Foo {

   public Bar () {
      super (doSmth());
      ...
   }

   private static String doSmth () {
      //what I can NOT do here?
   }
}
Run Code Online (Sandbox Code Playgroud)

我想知道它安全吗?doSmth方法有什么限制吗?

Tof*_*eer 5

简单的规则是不要直接或间接地从构造函数中访问"this"对象.

这意味着你不应该从构造函数中调用可重写的方法,也不应该调用调用可重写方法的方法,或者调用调用可重写方法的方法的方法,或者......你明白了.

这也意味着你不应该将"this"传递给任何东西,因为另一件事可以调用一个可重写的方法.

在你的特殊情况下,你有什么是好的.如果要改为:

class Bar extends Foo 
{
    public Bar () {
        super (doSmth(this));
        ...
    }

    private static String doSmth (Bar bar) {
        //what I can NOT do here?
   }
}
Run Code Online (Sandbox Code Playgroud)

然后你会有一个(潜在的)问题因为doSmth可以在Bar的子类中调用一个依赖于尚未初始化的数据的override方法.

以下是可能发生的情况的示例:

public class Main
{
    public static void main(final String[] argv)
    {
        final A a;

        a = new B();
        a.foo();
    }
}

abstract class A
{
    protected A()
    {
        bar(this);
    }

    private static void bar(final A a)
    {
        a.foo();
    }

    public abstract void foo();
}

class B extends A
{
    final String str;

    public B()
    {
        super();
        str = "Hello, World!";
    }

    public void foo()
    {
        System.out.println("str - " + str);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以,只要你不调用任何被覆盖的方法,你就是好的.但是,最安全的做法就是遵循"规则",即永远不要在构造函数之外传递它,也不要直接或间接地从构造函数中调用可重写(非最终)方法.