java - 为什么java要求构造函数的第一行要调用父构造函数?如果我们绕过这个要求,会有什么陷阱吗?

标签 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?
   }
}

请问安全吗? doSmth 方法有什么限制吗?

最佳答案

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

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

这也意味着您不应该将“this”传递给任何东西,因为其他东西可以调用可覆盖的方法。

在您的特定情况下,您所拥有的很好。如果要更改为:

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

    private static String doSmth (Bar bar) {
        //what I can NOT do here?
   }
}

然后你会遇到一个(潜在的)问题,因为 doSmth 可以在 Bar 的子类中调用一个重写方法,该方法依赖于尚未初始化的数据。

这是一个可能发生的例子:

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

因此,只要您不调用任何重写的方法就可以了。然而,最安全的做法是遵循从不将 this 传递到构造函数之外并且从不直接或间接从构造函数调用可覆盖(非最终)方法的“规则”。

关于java - 为什么java要求构造函数的第一行要调用父构造函数?如果我们绕过这个要求,会有什么陷阱吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3160370/

相关文章:

java - 如何设置mouseClicked事件?

c++ - 在 C++ 中,当它们具有依赖项时,我应该如何在初始化列表中强制执行组合对象构造函数的顺序

c++ - 构造函数中的构造函数中的绑定(bind)

java - 将 JButton 控件添加到 JApplet 并且 JButton 填满整个屏幕

java - 如何将 GMT 偏移值转换为 +/- HH :MM

java构造函数不能应用于给定类型android studio

c# - 派生类的构造函数可以比其基类的构造函数有更多的参数吗?

c++ - 处理 CTOR 抛出的异常?

java - 使用 Java 技术存储 UII 和 PII 的加密算法

java - 无法将 Java 代码转换为 Kotlin 以实现 OnChangeListener