Что такое предупреждение «this-escape» и как с ним справиться?

Я изо всех сил пытаюсь найти ресурсы по этому вопросу, и тем не менее, многие из моих классов сталкиваются с этой ошибкой, когда я компилирую свой код на последней версии 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

Может кто-нибудь помочь мне с тегами? Я чувствую, что здесь есть куда расти, но не могу придумать, что подойдет лучше.

davidalayachew 28.09.2023 04:31

Пожалуйста, предоставьте минимальный воспроизводимый пример и полное предупреждение/ошибку компилятора.

Mark Rotteveel 28.09.2023 10:25

Вопрос по этому выпуску вчера

DuncG 28.09.2023 13:25

@MarkRotteveel Я сделал это и отредактировал вопрос.

davidalayachew 28.09.2023 23:44

@DuncG Это, безусловно, та же проблема с источником. Хотя я думаю, что мой вопрос тоже полезен, поскольку он показывает, как люди чаще взаимодействуют с этим предупреждением.

davidalayachew 28.09.2023 23:45

обычно такие вопросы встречаются при выпуске новой версии (иногда и для функций предварительного просмотра)... :-/

user85421 29.09.2023 00:23

@user85421 user85421 Если вы подразумеваете критику моего вопроса, я готов ее услышать. Однако я не понимаю ваш комментарий как таковой.

davidalayachew 29.09.2023 01:29
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
7
114
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вот запись в системе ошибок JDK, в которой представлено это новое предупреждение — https://bugs.openjdk.org/browse/JDK-8299995

Короче говоря, предупреждение this-escape предназначено для предупреждения вас, когда подкласс может @Override использовать метод, который также вызывается в конструкторе суперкласса.

Это опасно, поскольку переопределение метода, используемого в конструкторе, позволяет подклассу непреднамеренно внести ошибку во время инициализации подкласса. Что, если этот метод зависит от состояния, которое еще не создано, поскольку мы все еще находимся в суперконструкторе? В конце концов, вы не можете ничего сделать в конструкторе подкласса до вызова суперконструктора (пока ).

Есть несколько способов исправить это.

  1. Используйте в конструкторе только те методы, которые нельзя переопределить.

    • static методы.

    • final методы.

    • private методы.

  2. Сделайте сам урок final.

  3. Не передавайте/используйте this с самого начала — вместо этого передайте тот конкретный компонент this, который вам нужен.

    • По сути, перестаньте лениться и четко сформулируйте, что вам нужно. Не передавайте просто свой объект God — передавайте только те атрибуты, которые вам нужны.

Обратите внимание: эти правила применяются рекурсивно. Это означает, что когда вы вызываете метод в конструкторе, этот метод не только должен быть «непереопределяемым», но и методы, в которые этот метод передает 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 29.09.2023 00:33

@user85421 user85421 Полезная информация, ты вм.

davidalayachew 29.09.2023 01:30

@Holger Как ни странно, ваш комментарий заставил меня понять, что высказывание «методы, которые невозможно переопределить» неверно. Мой ответ нуждается в серьезной доработке. В ходе выполнения.

davidalayachew 30.09.2023 05:06

@Holger Отредактировано, чтобы включить нюанс. Еще раз спасибо за ваш комментарий. Моего ответа так и не хватило бы, но я опробовал то, что вы сказали, и обнаружил несколько неточностей, которые не были учтены в моем первоначальном ответе.

davidalayachew 30.09.2023 07:00

@Holger Исправлено, посмотрим, можно ли его улучшить.

davidalayachew 04.10.2023 11:06

Другие вопросы по теме