Для чего в java используются фигурные скобки

5 скрытых cекретов в Java

Привет, Хабр! Представляю вашему вниманию перевод статьи «5 Hidden Secrets in Java» автора Justin Albano.

Хотите стать джедаем Java? Раскройте древние секреты Java. Мы сосредоточимся на расширении аннотаций, инициализации, на комментариях и интерфейсах enum.

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

Читатель должен понимать, что не все эти функции на самом деле скрыты, просто они часто не используются в повседневном программировании. Некоторые из них могут быть очень полезны в подходящий момент, тогда как использование других – почти всегда плохая идея, и показаны они в этой статье, чтобы заинтересовать читателя (и возможно рассмешить его или ее). Читатель также должен сам принимать решение когда использовать функции, описанные в этой статье: «То, что это можно сделать, не означает, что это нужно делать».

1. Реализация аннотаций

Начиная с Java Development Kit (JDK) 5, аннотации являются неотъемлемой частью многих приложений и сред Java. В подавляющем большинстве случаев аннотации применяются к конструкциям, таким как классы, поля, методы и т.д. Однако их можно использовать и как реализуемые интерфейсы. Например, предположим, у нас есть следующее определение аннотации:

Обычно мы применяем эту аннотацию к методу, как показано ниже:

Затем мы можем обработать эту аннотацию, как это описано в Создание аннотаций в Java. Если бы мы также хотели создать интерфейс, позволяющий создавать тесты как объекты, нам пришлось бы создать новый интерфейс, назвав его чем-то другим, а не Test:

Далее мы можем создать экземпляр объекта TestInstance:

Хотя наша аннотация и интерфейс практически идентичны, с очень заметным дублированием, похоже что нет способа объединить эти две конструкции. К счастью, внешность обманчива, и есть метод для объединения этих двух конструкций: Реализация аннотации:

Обратите внимание, что мы должны реализовать метод annotationType и также возвращать тип аннотации, поскольку это неявная часть интерфейса Annotation. Хотя почти во всех случаях реализация аннотации не являются правильным решением для проектирования (компилятор Java будет показывать предупреждение при реализации интерфейса), это может быть полезно в некоторых случаях, например в annotation-driven framework.

2. Нестатические блоки инициализации.

В Java, как и в большинстве объектно-ориентированных языков программирования, объекты создаются исключительно с использованием конструктора (с некоторыми исключениями, такими как десериализация объектов Java). Даже когда мы создаем статические фабричные методы для создания объектов, мы просто заключаем вызов в конструктор объекта, чтобы создать его экземпляр. Например:

Поэтому, когда мы хотим инициализировать объект, мы объединяем логику инициализации в конструкторе объекта. Например, устанавливаем поле name класса Foo в его параметризованном конструкторе. Хотя может показаться обоснованным предположение, что вся логика инициализации находится в конструкторе или наборе конструкторов для класса, в Java это не так. Вместо этого мы можем использовать нестатические блоки инициализации чтобы выполнить код при создании объекта:

Нестатические блоки инициализации указываются путем добавления логики инициализации в набор фигурных скобок в определение класса. Когда объект создается, сначала вызываются нестатические блоки инициализации, а затем конструкторы объекта. Обратите внимание, что можно указать более одного нестатического блока инициализации, и в этом случае каждый вызывается в том порядке, в котором он указан в определении класса. Помимо нестатических блоков инициализации, мы также можем создавать и статические, которые выполняются когда класс загружается в память. Чтобы создать статический блок инициализации, мы просто добавляем ключевое слово static:

Когда в классе присутствуют все три метода инициализации (конструкторы, нестатические блоки инициализации и статические блоки инициализации), статические всегда выполняются первыми (когда класс загружается в память) в порядке их объявления, затем выполняются нестатические блоки инициализации в порядке, в котором они объявлены, а после них – конструкторы. Когда вводится суперкласс, порядок выполнения немного меняется:

Если мы выполним этот код, то получим следующий вывод:

Обратите внимание на то что статические блоки инициализации были выполнены только один раз, даже если были созданы два объекта Foo. Хотя нестатистические и статические блоки инициализации могут быть полезны, логика инициализации должна быть помещена в конструкторы, а методы (или статические методы) должны использоваться в случаях когда сложная логика требует инициализации состояния объекта.

3. Двойная скобка инициализации

Многие языки программирования включают в себя некоторый синтаксический механизм для быстрого и краткого создания списка или карты (или словаря) без использования подробного шаблонного кода. Например, C ++ включает в себя инициализацию скобок, которая позволяет разработчикам быстро создавать список перечисляемых значений или даже инициализировать целые объекты, если конструктор для объекта поддерживает эту функцию. К сожалению, до JDK 9 такая функция не была реализована (об этом позже). Чтобы просто создать список объектов, мы бы сделали следующее:

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

Инициализация с двойной скобкой, которая получила свое название от набора двух открытых и закрытых фигурных скобок, на самом деле представляет собой совокупность нескольких синтаксических элементов. Сначала мы создаем анонимный внутренний класс, который расширяет класс ArrayList. Поскольку ArrayList не имеет абстрактных методов, мы можем создать пустое тело для анонимной реализации:

Используя этот код, мы по существу создаем анонимный подкласс, ArrayList – точно такой же, как и оригинальный ArrayList. Одно из основных отличий в том, что наш внутренний класс имеет неявную ссылку на содержащий класс (в форме захваченной this переменной), т.к. мы создаем нестатический внутренний класс. Это позволяет нам написать некоторую интересную, если не запутанную логику. Например, добавление этой переменной к анонимному внутреннему классу, инициализированному двойной скобкой:

Если бы этот внутренний класс был определен как статический, у нас не было бы доступа к Foo.this. Например, следующий код, который создает статический FooArrayList внутренний класс, не имеет доступа к Foo.this ссылке и поэтому он не компилируется:

Возобновляя конструкцию нашей инициализированной двойной скобкой ArrayList, как только был создан нестатический внутренний класс, мы используем нестатические блоки инициализации, как описано выше, чтобы добавить три начальных элемента, при создании экземпляра анонимного внутреннего класса. Когда анонимный внутренний класс создан и когда существует только один объект анонимного внутреннего класса, мы можем сказать что создали нестатический внутренний объект, который добавляет три начальных элемента при его создании. Это будет видно, если мы разделим пару фигурных скобок, где одна фигурная скобка представляет собой определение анонимного внутреннего класса, а другая обозначает начало логики инициализации экземпляра:

Хотя этот трюк может быть полезен, JDK 9 (JEP 269) заменил полезность этого трюка набором статических фабричных методов для List (а также многих других типов коллекций). Например, мы могли бы создать List раньше, используя эти статические фабричные методы, как показано далее:

Эта статическая фабричная техника используется по двум основным причинам: (1) не создается анонимный внутренний класс и (2) для сокращения стандартного кода, необходимого для создания List. Следует помнить что в таком случае полученный результат List является неизменным и не может быть изменен после его создания. Чтобы создать изменяемый List файл с любыми начальными элементами, нам приходится использовать обычный метод или метод с двойной скобкой инициализации.

Обратите внимание что простая инициализация, двойная скобка и статические фабричные методы JDK 9 не просто доступны для List. Они доступны для Set и Map объектов, как показано в следующем фрагменте:

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

4. Исполняемые комментарии

Комментарии являются неотъемлемой частью почти каждой программы, и основное преимущество комментариев заключается в том, что они не выполняются. Это становится еще более очевидным, когда мы закомментируем строку кода в нашей программе: мы хотим сохранить код в нашем приложении, но не хотим, чтобы он выполнялся. Например, следующая программа в результате выводит «5»:

Многие думают что комментарии никогда не выполняются, но это не совсем верно. Например, что выведет следующий фрагмент кода?

Вы могли предположить что это снова 5, но если мы запустим приведенный выше код, то увидим 8 на выходе. Причиной этой «ошибки» является символ Unicode \u000d; этот символ на самом деле является возвратом каретки Unicode, и исходный код Java используется компилятором как текстовые файлы в формате Unicode. Его добавление в код присваивает значению value = 8 в строке, идущей за комментарием, обеспечивая его выполнение. Это означает, что приведенный выше фрагмент кода фактически равен следующему:

Хотя это кажется ошибкой Java, на самом деле это специально добавленная функция в язык. Первоначальная цель состояла в том, чтобы создать независимый от платформы язык (отсюда создание виртуальной машины Java или JVM), и функциональная совместимость исходного кода является ключевым аспектом этой цели. Позволяя исходному коду Java содержать символы Unicode, мы можем использовать нелатинские символы универсальным способом. Это гарантирует, что код, написанный в одном регионе мира (который может содержать нелатинские символы, например в комментариях), может быть выполнен в любом другом. Для получения дополнительной информации см. Раздел 3.3 Спецификации языка Java или JLS.

Если поместить вышеупомянутый код в файл с именем Ugly.java и запустить его, то будет напечатано Hello world на стандартном выходе. Если мы преобразуем эти символы Юникода в символы Американского Стандартного Кода для Обмена Информацией (ASCII), то получим следующую программу:

Итак, символы Unicode могут быть включены в исходный код Java, однако если они не требуется настоятельно не рекомендуется их использовать (например, включать нелатинские символы в комментарии). Если они все же требуются, убедитесь, что они не включают символы, такие как возврат каретки, которые изменяют ожидаемое поведение исходного кода.

5. Реализация интерфейса Enum

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

Однако мы можем заставить наш enums реализовывать интерфейс и обеспечить реализацию для его абстрактных методов следующим образом:

Теперь мы можем использовать экземпляр Person везде, где требуется Speaker объект. Более того, мы также можем обеспечить реализацию абстрактных методов интерфейса на постоянной основе (так называемые методы, специфичные для констант):

В отличие от некоторых других секретов в этой статье, эту технику следует использовать только там, где это необходимо. Например, если enum константа, такая как JOE или JIM, может использоваться вместо интерфейса, такого как Speaker, то enum определяющее константу, должен реализовывать этот тип интерфейса. Для получения дополнительной информации см. Пункт 38 (стр. 176-9) Effective Java, 3rd Edition.

Источник

Что обозначает символ ‘<' (фигурная скобка) в Java?

В настоящее время я изучаю Java, и мне был задан вопрос, который, кажется, не поддается простому ответу:

Я потратил немало времени на поиск единственного определения этого символа в контексте Java, но не нашел здесь ничего, что было бы достаточно.

Каково всеобъемлющее определение того, что обозначает открывающая фигурная скобка в Java?

2 ответа

Вопрос вашего инструктора кажется не таким уж большим, потому что в Java нет единого значения символа <.

В контексте метода или типа (класс / интерфейс / перечисление / аннотация) символ <используется для обозначения начала тела класса или метода:

Его также можно использовать внутри класса для объявления блока инициализатора или статического инициализатора:

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

В большинстве этих контекстов, как указывалось в комментариях, скобка вводит новую область видимости. Блоки операторов, тела классов, тела инициализаторов и тела функций представляют новую область видимости, и это определенно важно иметь в виду. (Однако инициализация массива этого не делает.)

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

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

Фигурные скобки являются обязательными в некоторых случаях, например:

А иногда это необязательно, например:

Есть много других случаев, в которых используются фигурные скобки: вложенные классы, анонимные классы, инициализаторы, статические инициализаторы и многое другое. В каждом случае мы используем один и тот же синтаксис (фигурные скобки), но он имеет разную семантику.

Источник

Для чего в java используются фигурные скобки

Для чего в java используются фигурные скобки. Смотреть фото Для чего в java используются фигурные скобки. Смотреть картинку Для чего в java используются фигурные скобки. Картинка про Для чего в java используются фигурные скобки. Фото Для чего в java используются фигурные скобки

Для чего в java используются фигурные скобки. Смотреть фото Для чего в java используются фигурные скобки. Смотреть картинку Для чего в java используются фигурные скобки. Картинка про Для чего в java используются фигурные скобки. Фото Для чего в java используются фигурные скобки

Для чего в java используются фигурные скобки. Смотреть фото Для чего в java используются фигурные скобки. Смотреть картинку Для чего в java используются фигурные скобки. Картинка про Для чего в java используются фигурные скобки. Фото Для чего в java используются фигурные скобки

Тело класса, метода или конструктора относится к блочной конструкции.

Обратите внимание, что согласно Разделу 4.8.3.1, любой инициализатор массива также может рассматриваться как блочная конструкция.

Фигурные скобки ставятся согласно стилю Кернигана и Ритчи («Египетские скобки») для непустых блоков и блочных конструкций:

Пустой блок или пустая блочная конструкция может следовать стилю K & R (как описано в Разделе 4.1.2). Также возможно, чтобы такой блок был закрыт сразу же после открытия, без символов или разрыва строки внутри <>. Это правило не относится к случаю, когда блок является частью многоблочного выражения, которое содержит if-else или try-catch-finally.

2. Когда строка переносится на операторе присваивания, перенос обычно делается после символа, но приемлемо и другое решение

Это также применимо к двоеточию для цикла for-each.

При переносе строки каждая следующая ее подстрока (каждое продолжение строки) смещается как минимум на 4 пробела относительно предыдущей.

Когда продолжений строки несколько, смещение может варьироваться в пределах 4 пробелов по желанию автора. По общему правилу, два продолжения строки могут иметь одинаковое смещение тогда и только тогда, когда они начинаются с синтаксически параллельных элементов.

В Разделе 4.6.3 даются указания по использованию различного количества пробелов для выравнивания элементов кода относительно предыдущих строк.

Одна пустая строка всегда ставится:

1. Между следующими друг за другом членами или инициализаторами класса: полями, конструкторами, методами, вложенными классами, статическими и динамическими блоками инициализации

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

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

Помимо требований самого языка или прочих правил данного документа, а также не считая литералов и комментариев (в т.ч. Javadoc), одиночные пробелы из таблицы ASCII могут присутствовать только в следующих местах:

1. При разделении любого зарезервированного слова, такого как if, for или catch, и открывающей круглой скобки «(», которая следует за ним

2. При разделении любого зарезервированного слова, такого как else или catch, и закрывающей фигурной скобки «>», которая следует за ним

4. По обе стороны от любого бинарного или тернарного оператора

5. После «,:;» или закрывающей круглой скобки «)» при приведении типа

6. По обе стороны от двойной косой черты «//» при создании комментария в той же строке кода. Здесь разрешены, но не необходимы несколько пробелов

7. Между объявлением типа и именем переменной: List list

Источник

Принцип восприятия фигурных скобок в Java

Меня интересует, есть ли какие-либо особенности блоков, не имеющих такой привязки?

Где-то видел насчет этого какую-то информацию о том, что есть, к примеру, в классах некие статические блоки инициализации и прочее, типа:

Код в блоке воспринимается как что? В чем разительные отличия?

Для чего в java используются фигурные скобки. Смотреть фото Для чего в java используются фигурные скобки. Смотреть картинку Для чего в java используются фигурные скобки. Картинка про Для чего в java используются фигурные скобки. Фото Для чего в java используются фигурные скобки

2 ответа 2

В фигурные скобки помещаются:

Тело интерфейса или класса:

Тело метода:

Тело условного оператора:

Тело цикла:

Набор элементов для инициализации массива:

Блок статической инициализации (выполняется при первой загрузке класса):

Блок НЕстатической инициализации (выполняется после отработки любого конструктора данного класса):

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

Синтаксисом языка принято, что область действия каждого оператора (начало и конец) должна быть обозначена фигурными скобками. Верхний уровень, как правило, обозначается оператором class и его область действия может включать инициализацию полей, блок статической и нестатической инициализации, конструкторы и методы. Границы (начало и конец) конструкторов, методов и блоков инициализации так же обязаны быть обозначены фигурными скобками. Кроме того, фигурными скобками может быть объединено несколько операторов в отдельный исполняемый блок (включая и один оператор, как это ни странно :)).

Таким образом в структуре вида:

Мы определяем блок нестатической инициализации. Вывод значения «a» будет выполнено при каждом создании этого экземпляра класса (объекта).

Если фигурные скобки опустить, то возникает ошибка, поскольку в структуре класса, без отдельного выделения в блок кода фигурными скобками, может производиться только инициализация полей класса:

Подробнее про виды инициализации в классе.

Ну и ответ на ваш вопрос: В первом случае получается синтаксическая ошибка, так как операторы языка не могут существовать вне блока кода, определенного фигурными скобками, во втором случае вы определяете блок нестатической инициализации. Здесь нет никакой магии.

Источник

Java Code Style: как правильно оформлять код Java

Статья об именах переменных, классов и методов, скобках, комментариях, форматировании кода и других правилах хорошего тона, принятых в языке Javа.

Для чего в java используются фигурные скобки. Смотреть фото Для чего в java используются фигурные скобки. Смотреть картинку Для чего в java используются фигурные скобки. Картинка про Для чего в java используются фигурные скобки. Фото Для чего в java используются фигурные скобки

Для чего в java используются фигурные скобки. Смотреть фото Для чего в java используются фигурные скобки. Смотреть картинку Для чего в java используются фигурные скобки. Картинка про Для чего в java используются фигурные скобки. Фото Для чего в java используются фигурные скобки

В языке Java, как и во многих других языках программирования, есть неофициальные, но принятые сообществом разработчиков соглашения по оформлению кода. Давайте попробуем разобраться, что это такое, как работает и почему важно.

Зачем нужен единый стиль кода

Java Code Style — это рекомендации и соглашения о стиле кода, собранные вместе. Например:

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

Причины, по которым разработчики пришли к таким соглашениям, логичны и просты:

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

Для чего в java используются фигурные скобки. Смотреть фото Для чего в java используются фигурные скобки. Смотреть картинку Для чего в java используются фигурные скобки. Картинка про Для чего в java используются фигурные скобки. Фото Для чего в java используются фигурные скобки

Преподаватель Skillbox. Пишет про Java, учит Go. Помнит рассвет PHP и как «грабить корованы».

Форматирование на практике

Стиль не играет роли для компьютера, но важен для чтения кода человеком. Наше зрение устроено так, что сперва получает и анализирует образы, а только затем мы вдаёмся в детали. А если блоки исходного текста унифицированы, разработчик понимает, что перед ним за конструкция, даже не вникая в сам код.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *