Я изо всех сил пытаюсь найти ресурсы по этому вопросу, и тем не менее, многие из моих классов сталкиваются с этой ошибкой, когда я компилирую свой код на последней версии Java (21).
Вот пример кода.
public class ThisEscapeExample
{
public Object o;
public ThisEscapeExample()
{
this.overridableMethod();
}
public void overridableMethod()
{
this.o = new Object();
}
}
И вот моя команда компиляции.
javac -Xlint:all ThisEscapeExample.java
ThisEscapeExample.java:9: warning: [this-escape] possible 'this' escape before subclass is fully initialized
this.overridableMethod();
^
1 warning
Пожалуйста, предоставьте минимальный воспроизводимый пример и полное предупреждение/ошибку компилятора.
Вопрос по этому выпуску вчера
@MarkRotteveel Я сделал это и отредактировал вопрос.
@DuncG Это, безусловно, та же проблема с источником. Хотя я думаю, что мой вопрос тоже полезен, поскольку он показывает, как люди чаще взаимодействуют с этим предупреждением.
обычно такие вопросы встречаются при выпуске новой версии (иногда и для функций предварительного просмотра)... :-/
@user85421 user85421 Если вы подразумеваете критику моего вопроса, я готов ее услышать. Однако я не понимаю ваш комментарий как таковой.
Вот запись в системе ошибок JDK, в которой представлено это новое предупреждение — 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;
}
}
Кстати, даже с JEP447 мало что можно будет сделать для инициализации экземпляра, поскольку контекст предварительной конструкции не позволит ссылаться на this
(аналогично контексту static
)
@user85421 user85421 Полезная информация, ты вм.
@Holger Как ни странно, ваш комментарий заставил меня понять, что высказывание «методы, которые невозможно переопределить» неверно. Мой ответ нуждается в серьезной доработке. В ходе выполнения.
@Holger Отредактировано, чтобы включить нюанс. Еще раз спасибо за ваш комментарий. Моего ответа так и не хватило бы, но я опробовал то, что вы сказали, и обнаружил несколько неточностей, которые не были учтены в моем первоначальном ответе.
@Holger Исправлено, посмотрим, можно ли его улучшить.
Может кто-нибудь помочь мне с тегами? Я чувствую, что здесь есть куда расти, но не могу придумать, что подойдет лучше.