Анонимные классы-члены в Java

Что касается анонимных классов, в документации Oracle говорится, что ...

They are like local classes except that they do not have a name. Use them if you need to use a local class only once

Теперь, учитывая, что локальные классы (насколько мне известно) являются классами, определенными в методе (или какой-либо другой локальной конструкции), например, следующим ... (где MyInterface - это интерфейс с абстрактным методом тестирования)

public void localTest(){
    MyInterface mi = new MyInterface(){
        @Override
        public void test(){System.out.println("test");};
    };
}

Вышесказанное в порядке и подпадает под определение, приведенное выше, однако я также могу определить следующее ...

class MyClass{

    MyInterface mi = new MyInterface(){
        @Override
        public void test(){System.out.println("test");};
    };
}

Это не входит в метод, поэтому не является классом «Локальный» и поэтому не подпадает под приведенное выше определение. Могу ли я где-нибудь прочитать об этих типах анонимных классов (анонимных классов-членов, если хотите). Что они собой представляют, если не анонимные классы, как определено?

Это все еще анонимные классы. То, что вы показали, не является определением, это объяснение - обратите внимание на часть локальных классов нравиться. Даже анонимный класс, используемый в объявлении поля, является нравиться локальным классом.

Jon Skeet 16.03.2018 16:41

что, если вы измените void localTest() на возврат MyInterface, вы просто опубликуете переменную, которая ссылается на ваш анонимный класс, даже если к ссылке можно получить доступ вне вашего метода. Таким образом, класс по-прежнему анонимный - он локальный, поскольку у вас не может быть других экземпляров этого класса. Итак, класс локальный (объект не нужен)

Maciej 16.03.2018 16:43

То, что вы показываете, - это не местный класс.

Mark Rotteveel 16.03.2018 16:44

@LuiggiMendoza Нет, локальный класс определяется отдельно от своего создания, оба показанных примера являются простыми анонимными классами. У местных классов есть собственное название.

Mark Rotteveel 16.03.2018 16:46

Когда вы добавляете инициализатор поля в определение поля, вы фактически добавляете строку кода в конструктор по умолчанию. Я предполагаю, что если вы посмотрите на скомпилированный код, вероятно, анонимный класс будет связан с методом конструктора.

StriplingWarrior 16.03.2018 16:49

@MarkRotteveel, спасибо за комментарий, не могли бы вы указать мне на источник, в котором говорится, что локальный класс должен иметь имя / не может быть анонимным, поскольку это не было моим пониманием. Спасибо!

Zippy 16.03.2018 16:51

Как и все эти вещи, посмотрите спецификацию языка Java, в частности, 14.3. Объявления локальных классов говорит: «Локальный класс - это вложенный класс (§8 (Классы)), который не является членом какого-либо класса и имеет имя (§6.2, §6.7)».

Mark Rotteveel 16.03.2018 16:53

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

Zippy 16.03.2018 16:59
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
8
69
2

Ответы 2

Локальные классы определены как здесь как определяемые в блокировать, а не в методе. Ваш пример все еще анонимный класс. Если вы находитесь в процессе обучения, обратите внимание, что вы можете фактически заменить объявление лямбда-выражением, например:

MyInterface mi = () -> System.out.println("test");

Кроме того, анонимные классы описываются только как локальные классы нравиться, что означает, что первые не обязательно являются подмножеством вторых.

Хммм ... Хорошо, спасибо, @A.Bandtock. Мы действительно включаем здесь фигурные скобки класса, если да, не могли бы вы помочь мне понять, почему у нас есть термины «внутренний класс» и «локальный класс», когда это будет означать, что все внутренние классы являются локальными классами (если я не ошибаюсь) - кажется немного лишним ... спасибо - просто пытаюсь понять мою терминологию :-)

Zippy 16.03.2018 17:06

@Zippy Локальные классы - это внутренние классы, но нестатические классы, вложенные внутри другого класса, являются внутренними классами также (и они гораздо более распространены, чем локальные классы). См. 8.1.3. Внутренние классы и закрывающие экземпляры.

Mark Rotteveel 16.03.2018 17:07

@Zippy Если вы читаете ссылку там, она фактически дает вам определение блока как «который представляет собой группу из нуля или более операторов между сбалансированными фигурными скобками», что в основном переводится как «что-то между { и }. Все локальные классы являются внутренними классами, различие таково, как описано в @Mark Rotteveel.

A. Bandtock 16.03.2018 17:10

Я знаю, что все локальные классы являются внутренними классами, но это также означает, что все внутренние классы также являются локальными классами, правильно?

Zippy 16.03.2018 17:11

@Zippy Согласно ответам здесь: stackoverflow.com/questions/10392725/… моя интерпретация документации кажется неправильной ... Для хорошей сводной проверки здесь: docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html

A. Bandtock 16.03.2018 17:12

@Zippy По словам docs.oracle.com/javase/tutorial/java/javaOO/nested.html, «Есть два особых типа внутренних классов: локальные классы и анонимные классы». Это говорит о том, что все внутренние классы могут быть помещены в одну из этих категорий, что указывает на то, что моя первоначальная интерпретация была верный. В любом случае семантика этого позволяет использовать «внутренний класс» в любой ситуации.

A. Bandtock 16.03.2018 17:16

Нет, это неверное толкование. У вас есть внутренние классы (нестатические классы, определенные внутри другого класса), и небольшое подмножество внутренних классов («особые виды») - это локальные классы и анонимные классы; все остальные - «нормальные» внутренние классы.

Mark Rotteveel 16.03.2018 17:20

Оба примера, которые вы показываете, являются анонимными классами. Настоящий локальный класс - это определение класса в методе (или другом блоке кода) с фактическим именем (то есть не анонимным). Учитывая ваш пример, эквивалентный локальный класс будет:

public void localTest(){
    class LocalClass implements MyInterface {
        @Override
        public void test(){
            System.out.println("test");
        }
    }

    MyInterface mi = new LocalClass();
}

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

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

Кроме того, поскольку у вас действительно есть определение класса, вы также можете определять и вызывать методы, которые не определены в интерфейсе или суперклассе. До Java 10 и появления var это было невозможно с анонимными классами.

Другие незначительные отличия заключаются в том, что локальные классы могут быть абстрактными или окончательными, а локальные классы могут расширять (и расширяться) другими локальными классами, в то время как анонимный класс не является окончательным и не может быть абстрактным, но анонимные классы не могут быть расширены другими классами.

Для получения дополнительной информации о различиях между локальными классами и анонимными классами см. Спецификацию языка Java, в частности 14.3. Объявления локальных классов и 15.9.5. Объявления анонимных классов и связанные разделы.

Очень хорошее указание на то, что редко (если вообще когда-либо) нужно использовать локальные классы. Они усложняют и ухудшают ремонтопригодность. Стоит отметить, что анонимные классы, наоборот, могут быть чрезвычайно полезными.

A. Bandtock 16.03.2018 17:00

@ A.Bandtock Если честно, поскольку Java 8 и методы обрабатывают, я считаю, что мне также редко нужно использовать анонимные классы.

Mark Rotteveel 16.03.2018 17:02

Спасибо, я пытаюсь понять правильную терминологию для экзамена OCP. А также просто потому, что мне просто нравится знать правильную терминологию. Это просто сбивает с толку, потому что анонимные классы описываются как «как локальные классы, но без имени».

Zippy 16.03.2018 17:44

Это потому, что они являются локальными классами нравиться, но у них нет имени. Быть нравиться чем-то не означает, что это то же самое.

Mark Rotteveel 16.03.2018 17:48

Действительно, @MarkRotteveel, но он также говорит: «Они похожи на локальные классы, за исключением того, что у них нет имени. Используйте их, если вам нужно использовать локальный класс только один раз, они упоминают локальные классы очень конкретно.

Zippy 16.03.2018 18:44

Важная фраза - только один раз. Как я конкретно упоминал в своем ответе, если у вас есть локальный класс, вы можете new несколько раз в разных частях вашего метода, а не с анонимным классом. Если вы new анонимный класс несколько раз в разных частях одного и того же метода, вы фактически используете два разных анонимных класса. Тем не менее, не зацикливайтесь на этом, местные классы - очень эзотерическая особенность (в большей степени, чем анонимные классы), и вы вряд ли когда-нибудь увидите их в реальной жизни.

Mark Rotteveel 16.03.2018 19:14

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