gpt4 book ai didi

java - "cannot reference this before supertype constructor has been called"的奇怪情况

转载 作者:搜寻专家 更新时间:2023-11-01 03:49:31 26 4
gpt4 key购买 nike

为什么这段代码不能编译?

public class A {
public class B extends A {
public B(A a) { }
}
void foo() {
A a = new A();
new B(a) { };
}
}

A.java:[7,17] 在调用父类(super class)型构造函数之前无法引用它

如果进行以下任何更改,则编译成功:

  • B 是私有(private)的而不是公共(public)的
  • 第 7 行读取 new B(A); 而不是 new B(A) { }

使用javac版本:1.6.0_20

最佳答案

应该注意的是,Eclipse、javac 和 Intellij IDEA 在这些片段方面表现出不同的行为。 javacJava Puzzlers 行为在此讨论中用作引用。

我能够将代码片段缩减为以下内容:

public class A {
class B extends A {
}
void foo() {
new B() { }; // DOES NOT COMPILE!!
}
}

此场景在 Java Puzzlers 中讨论,谜题 90:这很荒谬,很痛苦,它是父类(super class)!

给出的片段如下:

public class Outer {                   // "A"
class Inner1 extends Outer {} // "B"
class Inner2 extends Inner1 {} // "B" anonymous
}
// DOES NOT COMPILE!!

问题是由于默认构造函数的定义方式,我们确实有以下内容:

// Same as above but with default constructor included explicitly
public class Outer {
class Inner1 extends Outer {
Inner1() { super(); }
}
class Inner2 extends Inner1 {
Inner2() { super(); }
}
}
// STILL DOES NOT COMPILE!!

问题是 Inner2 的父类(super class)本身就是一个内部类 Inner1,因此 Inner2 的默认构造函数是非法的,因为它需要要提供给构造函数的封闭实例。

解决这个问题的“蛮力”方法是明确地提供一个合格的this表达式:

// "brute-force" fix
public class Outer {
class Inner1 extends Outer {
Inner1() { super(); }
}
class Inner2 extends Inner1 {
Inner2() { Outer.this.super(); }
}
}
// NOW COMPILES!

然而,谜题规定最好首先避免这种复杂情况。以下是一些引述:

This compiles, but it is mind-numbingly complex. There is a better solution: Whenever you write a member class, ask yourself, Does this class really need an enclosing instance? If the answer is no, make it static. Inner classes are sometimes useful, but they can easily introduce complications that make a program difficult to understand. They have complex interactions with generics (Puzzle 89), reflection (Puzzle 80), and inheritance (this puzzle). If you declare Inner1 to be static, the problem goes away. If you also declare Inner2 to be static, you can actually understand what the program does: a nice bonus indeed.

In summary, it is rarely appropriate for one class to be both an inner class and a subclass of another. More generally, it is rarely appropriate to extend an inner class; if you must, think long and hard about the enclosing instance. Also, prefer static nested classes to non-static. Most member classes can and should be declared static.

关于java - "cannot reference this before supertype constructor has been called"的奇怪情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32250452/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com