Как правильно создать внутренний класс Java?

У меня есть следующие классы Java:

public class Outer {
 ...
 private class Inner {
  ...
 }
 ...
}

Предположим, я внутри нестатического метода Outer. Какая разница, звоню ли я this.new Inner() или new Outer.Inner()? Гарантируется ли во втором случае, что новый Outer не будет создан?

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

Если вы объявляете внутренний класс, это в основном потому, что вы не будете использовать его где-либо еще. Но они все еще разные классы. Если вы создаете объект внешнего объекта, вам не нужно объявлять внутренний.

MadMax 15.12.2020 09:17

чтобы избежать этого this.new Inner() или new Outer.Inner(), вы можете объявить свой внутренний класс как класс static. private static class Inner

mtdot 15.12.2020 09:20

Я считаю, что два опубликованных вами вызова конструктора функционально идентичны (было бы другое дело, если бы вы написали new Outer().new Inner(). Но не было бы более полезным для вашего поиска опубликовать ошибку, которую вы пытаетесь устранить?

Jeroen Steenbeeke 15.12.2020 09:20

Спасибо, это был главный вопрос, идентичны ли эти две строки семантически. Но я думаю, что это вопрос знания стандарта Java, а не «веры», не так ли? :-)

Kolodez 15.12.2020 09:26

Если я не устраню свою ошибку, я могу опубликовать ее, но это слишком сложно объяснить, потому что я не знаю, в какой строке кода она появляется.

Kolodez 15.12.2020 09:27

Вы можете спросить себя: как он вообще теоретически сможет создать еще один экземпляр Outer? Поскольку вы не указываете его параметр конструктора, не может быть вызван пользовательский конструктор и, следовательно, не может быть создан другой Outer.

luk2302 15.12.2020 09:39

@Kolodez Вы не знаете, в какой строке возникает ошибка компиляции? Ошибки компиляции всегда указывают строку, так что это звучит неправильно.

Andreas 15.12.2020 09:44

Это не было ошибкой компиляции. Проблема заключалась в неожиданном поведении программы. Но я, наконец, нашел проблему. :-)

Kolodez 16.12.2020 18:35
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
5
8
153
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Они одинаковы, хотя оба излишне многословны.

Следующие 3 версии приводят к одному и тому же байт-коду:

class Outer {
    private class Inner {
    }
    void foo() {
        Inner a = this.new Inner();
        Inner b = new Outer.Inner();
        Inner c = new Inner();       // Recommended way to write it
    }
}

Байт-код

       0: new           #7                  // class Outer$Inner
       3: dup
       4: aload_0
       5: invokespecial #9                  // Method Outer$Inner."<init>":(LOuter;)V
       8: astore_1

       9: new           #7                  // class Outer$Inner
      12: dup
      13: aload_0
      14: invokespecial #9                  // Method Outer$Inner."<init>":(LOuter;)V
      17: astore_2

      18: new           #7                  // class Outer$Inner
      21: dup
      22: aload_0
      23: invokespecial #9                  // Method Outer$Inner."<init>":(LOuter;)V
      26: astore_3

Blank lines added to improve clarity.

new Outer.Inner(); иногда бывает полезно при создании экземпляра внутреннего общедоступного статического класса из другого места. Я думаю об этом как о дополнительном квалификаторе пакета/области.
Reto Höhener 15.12.2020 10:25

@RetoHöhener Хорошо, что вы так думаете, потому что это именно то, что есть. Точно так же this.new Inner(), или, скорее, other.new Inner(), полезен, когда вы хотите, чтобы объект Inner был связан с объектом Outer, отличным от this, что похоже на то, как вы можете получить доступ к полю, используя name или this.name, вы можете написать new Inner() или this.new Inner(), делает нет разницы.

Andreas 15.12.2020 11:08

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