dav*_*hew 1 java warnings scope compiler-warnings this-pointer
我很难找到这方面的资源,但是,当我在最新的 Java (21) 上编译代码时,我的很多类都遇到了这个错误。
这是一个代码示例。
public class ThisEscapeExample
{
public Object o;
public ThisEscapeExample()
{
this.overridableMethod();
}
public void overridableMethod()
{
this.o = new Object();
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的编译命令。
javac -Xlint:all ThisEscapeExample.java
ThisEscapeExample.java:9: warning: [this-escape] possible 'this' escape before subclass is fully initialized
this.overridableMethod();
^
1 warning
Run Code Online (Sandbox Code Playgroud)
这是引入此新警告的 JDK Bug 系统条目 - https://bugs.openjdk.org/browse/JDK-8299995
长话短说,该this-escape
警告是在子类可以@Override
使用超类构造函数中也调用的方法时向您发出警告。
这是危险的,因为重写构造函数中使用的方法会导致子类在子类初始化期间无意中引入错误。如果该方法依赖于尚未创建的状态,因为我们仍在超级构造函数中怎么办?毕竟,在调用超级构造函数之前(目前),您不能在子类的构造函数中执行任何操作。
有几种方法可以解决这个问题。
仅使用构造函数中不能被重写的方法。
static
方法。
final
方法。
private
方法。
自己制作课程final
。
不要传入/使用this
开头 - 相反,传入this
您需要的特定组件。
请注意 - 这些规则递归适用。这意味着,当您在构造函数中调用方法时,不仅该方法必须是“不可重写的”,而且该方法传递到的方法还this
必须匹配上述规则之一。如果您的顶级方法不可重写,但其中的方法之一是可重写的,并且该方法在其范围内,那么您将在编译时收到错误。这是一个例子。this
this-escape
import javax.swing.*;
public class GUI
{
private final JFrame frame;
public GUI()
{
this.frame = new JFrame();
this.frame.add(this.createBottomPanel());
}
//final! Does that mean we are safe?
final JPanel createBottomPanel()
{
final JButton save = new JButton();
save
.addActionListener
(
/*
* No. We get the warning here at the start of this lambda.
* The reason is because we have given this lambda the
* ability to call this.toString(), and we don't know when
* it will do that. Maybe now, maybe later. But if it does
* it now, then we could end up doing things before the
* object is fully created. And if that were to happen, then
* that would be a this-escape. So, the warning occurs here,
* to let you know that it is possible.
*/
actionEvent ->
{
this.toString();
}
)
;
return null;
}
}
Run Code Online (Sandbox Code Playgroud)