【问题标题】:Is calling super() constructor should be the very first line of the constructor?调用 super() 构造函数应该是构造函数的第一行吗?
【发布时间】:2012-05-23 20:48:12
【问题描述】:

调用super() 构造函数应该是构造函数的第一行吗?如果是,那为什么?为什么在构造函数调用前不能做一些简单的有限计算,比如构造函数参数计算?

我发现了一个可以用闭包规范调用的内部类构造函数:

class A {
    class Inner1 {
        Inner1() {
            // do something
        }
    }
}

class B {
    A a1 = new A();
    A a2 = new A();

    class Inner2 extends A.Inner1 {
         Inner2(boolean sel) {
             (sel?a1:a2).super();
         }
    }

}

这个案例表明我们可以为基类构造函数选择封闭实例。为什么选择逻辑应该如此有限?为什么不能写这样的东西

if( sel ) {  
    a1.super();
}
else {
    a2.super();
}

添加

通过我的问题,我的意思是限制可能类似于以下情况:

public class Base {

private final String content;

public Base(String content) {
    this.content = content;
}

public String getContent() {
    return content;
}

}


public class Derived extends Base {

public Derived(String content) {
    super(String.format("Current value of content is %s.", getContent()));
}


}

在后一种情况下,我:

1) 满足super()在第一行的要求

2) 违反构造顺序

3) 获得编译器错误“无法在显式调用构造函数时引用实例方法”

那么,为什么我们不能废除“第一线要求”而只依赖最后一个错误呢?

【问题讨论】:

  • super() 如果您使用它,则必须作为构造函数调用的第一行 - 但请检查此线程:stackoverflow.com/questions/9675431/… 或此:stackoverflow.com/questions/1168345/…
  • 谢谢!变通方法很有趣,但也很有趣,为什么要制作 Java,即如果我在调用 super 之前做某事有什么不好?例如,我可能只需要在调用 super 之前不访问实例成员。
  • @SuzanCioc 如果您在致电super() 之前做了一些事情。 Java 会停止你的程序并告诉你修复它。
  • @Suzan Cioc,birryree 提供的第二个链接涵盖了该问题
  • @Suzan 有一些语言(python)允许稍后或根本不调用超类的构造函数。这显然会产生不好的后果,但是我们都知道首先调用super() 并不能解决所有问题,并且会产生大量新问题。不过这是一种简化,因为这意味着我们不必将对象分配和初始化分成两个独立的部分。而且我认为它避免了一种会经常出现的问题。

标签: java constructor closures inner-classes superclass


【解决方案1】:

是的,对super() 的调用是构造函数中的第一次调用。

如此之多,以至于如果您忽略它,编译器将(尝试)为您插入调用。要了解原因,您需要了解 Java 设计者的哲学。 Gosling 一直属于计算机科学家的阵营,他们认为访问部分初始化的对象是计算机程序中更大的错误来源之一。因此,他设计了一个严格的初始化层次结构来帮助缓解这个问题。你是否同意这个哲学是没有实际意义的——但重要的是要认识到它在 Java 中的一个概念与引用与指针或真实的有界数组一样重要。应该注意的是,即使像 Objective C 这样允许您随时调用初始化的语言,也会竭尽全力强制执行初始化链接,除非它们需要通过约定而不是严格来执行语言规则。

我不确定您在示例中试图说明什么 - 但经过多年的 Java 开发后,我怀疑您会发现很多情况,您真的需要在调用 super 之前执行逻辑。

【讨论】:

    【解决方案2】:

    在调用该类的构造函数之前,构造函数调用与层次结构中每个类的 super 链接。由于Java中的所有类都继承自object类,所以每个类都会首先调用Object类的构造函数,原因是object的内存分配是由Object类的构造函数完成的

    【讨论】:

    • 但是,如果我用super() 编写一个长而单一的表达式与编写一些多行代码,主要区别是什么?
    • 你能解释一下吗?基本上,如果没有执行 Object 类的构造函数,那么您就没有对象可以使用。并且为了确保调用 Object 的构造函数,调用 super() 必须是第一行
    • 请看我的问题。我提供了两个扩展构造函数的代码,逻辑上是相同的,但Java只允许第一个
    猜你喜欢
    • 2012-06-19
    • 2015-12-18
    • 2018-05-06
    • 2013-02-18
    • 1970-01-01
    • 2017-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-24
    相关资源
    最近更新 更多