1. Обзор
При компиляции класса Java создается файл класса с тем же именем. Однако, в случае вложенных классов или вложенных интерфейсов, он создает файл класса с именем, сочетающий внутренние и внешние имена классов, включая знак доллара.
В этой статье мы увидим все эти сценарии.
2. Подробная информация
В Java мы можем написать класс в классе. Класс, написанный внутри, называется вложенным классом, а класс, в который находится вложенный класс, называется внешним классом. Область вложенного класса ограничена областью его прилагаемого класса.
Аналогичным образом, мы можем объявить интерфейс в другом интерфейсе или классе. Такой интерфейс называется вложенным интерфейсом.
Мы можем использовать вложенные классы и интерфейсы для логически групповых сущностей, которые используются только в одном месте. Это не только делает наш код более читаемым и управляемым, но и увеличивает инкапсуляцию.
В следующих разделах мы подробно обсудим каждый из них. Мы также посмотрим на enums.
3. Вложенные классы
Вложенный класс является классом, который объявляется внутри другого класса или интерфейса. Каждый раз, когда нам нужен отдельный класс, но все же мы хотим, чтобы класс вел себя как часть другого класса, вложенный класс является лучшим способом его достижения.
Когда мы компилировать файл Java, он создает .class файл для класса ограждения и отдельные файлы классов для всех вложенных классов. Сгенерированный файл класса для класса ограждения будет иметь то же имя, что и класс Java.
Для вложенных классов компилятор использует другую конвенцию именования – OuterClassName$NestedClassName.class
Прежде всего, давайте создадим простой класс Java:
public class Outer { // variables and methods... }
3.1. Статические вложенные классы
Как следует из названия, вложенные классы, которые объявлены статические называются статическими вложенными классами. В Java разрешается использовать только вложенные статический.
Статические вложенные классы могут иметь как статические, так и нестатическое поля и методы. Они привязаны к внешнему классу, а не к определенному экземпляру. Следовательно, нам не нужен экземпляр внешнего класса, чтобы получить к ним доступ.
Давайте объявим статический вложенный класс в нашем Внешние класс:
public class Outer { static class StaticNested { public String message() { return "This is a static Nested Class"; } } }
Когда мы компилировать наши Внешние класс , компилятор создает два файла класса, один для Внешние и еще один для СтатическаяНеупойс :
3.2. Нестатическое гнездование классов
Нестатическое вложенные классы, также называемые внутренние классы – связаны с экземпляром класса ограждения, и они могут получить доступ ко всем переменным и методам внешнего класса.
Внешний класс может иметь только общедоступный или по умолчанию доступ, в то время как внутренний класс может быть частным, общедоступный, защищенный или с доступом по умолчанию. Тем не менее, они не могут содержать статических элементов. Кроме того, нам нужно создать экземпляр внешнего класса, чтобы получить доступ к внутреннему классу.
Давайте добавим еще один вложенный класс в наш Внешние класс:
public class Outer { class Nested { public String message() { return "This is a non-static Nested Class"; } } }
Он генерирует еще один файл класса:
3.3. Местные классы
Локальные классы, также называемые внутренними классами, определяются в блоке – группе утверждений между сбалансированными скобками. Например, они могут быть в методе тела, для петля, или если статья. Область действия локального класса ограничена внутри блока так же, как и локальные переменные. Локальные классы при составлении отображаются как знак доллара с автоматически генерируемым номером.
Файл класса, генерируемый для локального класса, использует конвенцию именования — OuterClassName$1LocalClassName.class
Давайте объявим локальный класс в методе:
public String message() { class Local { private String message() { return "This is a Local Class within a method"; } } Local local = new Local(); return local.message(); }
Компилятор создает отдельный класс файла для нашей Местные класс:
Аналогичным образом, мы можем объявить местный класс в если статья:
public String message(String name) { if (StringUtils.isEmpty(name)) { class Local { private String message() { return "This is a Local class within if clause"; } } Local local = new Local(); return local.message(); } else return "Welcome to " + name; }
Несмотря на то, что мы создаем другой локальный класс с тем же названием, компилятор не жалуется. Он создает еще один класс файла и называет его с числом увеличилось:
3.4. Анонимные внутренние классы
Как следует из названия, анонимные классы являются внутренними классами без имени. Компилятор использует автоматически генерируемый номер после знака доллара, чтобы назвать файл класса.
Мы должны объявить и мгновенно анонимных классов в одном выражении в то же время. Они обычно расширяют существующий класс или реализуют интерфейс.
Рассмотрим быстрый пример:
public String greet() { Outer anonymous = new Outer() { @Override public String greet() { return "Running Anonymous Class..."; } }; return anonymous.greet(); }
Здесь мы создали анонимный класс, расширяя Внешние класс, и компилятор добавил еще один файл класса:
Аналогичным образом, мы можем реализовать интерфейс с анонимным классом.
Здесь мы создаем интерфейс:
interface HelloWorld { public String greet(String name); }
Теперь давайте создадим анонимный класс:
public String greet(String name) { HelloWorld helloWorld = new HelloWorld() { @Override public String greet(String name) { return "Welcome to "+name; } }; return helloWorld.greet(name); }
Рассмотрим пересмотренный список файлов классов:
Как мы видим, файл класса генерируется для интерфейса HelloWorld и еще один для анонимного класса с именем Внешни$ $2 .
3.5. Внутренний класс в интерфейсе
Мы видели класс внутри другого класса, далее, мы можем объявить класс в интерфейсе. Если функциональность класса тесно связана с функциональностью интерфейса, мы можем объявить ее внутри интерфейса. Мы можем пойти на этот внутренний класс, когда мы хотим написать реализацию по умолчанию для методов интерфейса.
Давайте объявим внутренний класс внутри нашего HelloWorld интерфейс:
interface HelloWorld { public String greet(String name); class InnerClass implements HelloWorld { @Override public String message(String name) { return "Inner class within an interface"; } } }
И компилятор генерирует еще один файл класса:
4. Вложенные интерфейсы
Вложенные интерфейсы, также известные как внутренние интерфейсы, объявлены внутри класса или другого интерфейса. Основная цель использования вложенных интерфейсов заключается в разрешении пространства имен путем группировки связанных интерфейсов.
Мы не можем напрямую получить доступ к вложенным интерфейсам. К ним можно получить доступ только с помощью внешнего класса или внешнего интерфейса. Например, Входные интерфейс внутри Карта интерфейс вложен и может быть доступен как Карта . Входные .
Давайте посмотрим, как создать вложенные интерфейсы.
4.1. Интерфейс внутри интерфейса
Интерфейс, заявленный внутри интерфейса, неявно общедоступен.
Давайте объявим наш интерфейс внутри HelloWorld интерфейс:
interface HelloWorld { public String greet(String name); interface HelloSomeone{ public String greet(String name); } }
Это позволит создать новый класс файла под названием HelloWorld$HelloSomeone для вложенного интерфейса.
4.2. Интерфейс внутри класса
Интерфейсы, заявленные внутри класса, могут принимать любой модификатор доступа.
Давайте объявим интерфейс внутри нашей Внешние класс:
public class Outer { interface HelloOuter { public String hello(String name); } }
Он будет генерировать новый файл класса с именем: Внешнийкласс$СтатическийКласс
5. Энумы
enum был введен в Java 5. Это тип данных, который содержит фиксированный набор констант, и эти константы являются примерами этого enum .
enum декларация определяет класс называется e num типа (также известного как перечисленный тип данных). Мы можем добавить много вещей к enum как конструктор, методы, переменные, и то, что называется постоянным конкретным телом класса.
Когда мы создаем enum , мы создаем новый класс, и мы неявно расширения Энум класса. Энум не может унаследовать любой другой класс или не может быть продлен. Тем не менее, он может реализовать интерфейс.
Мы можем объявить enum как отдельный класс, в его собственном файле источника или другой член класса. Давайте посмотрим все способы создания enum .
5.1. Энум как класс
Во-первых, давайте создадим простую enum :
enum Level { LOW, MEDIUM, HIGH; }
Когда он будет составлен, компилятор создаст файл класса с именем Уровень для нашего enum.
5.2. Энум в классе
Теперь давайте объявим вложенный enum в нашем Внешние класс:
public class Outer { enum Color{ RED, GREEN, BLUE; } }
Компилятор создаст отдельный классный файл под названием Внешни$ цвет для нашего вложенного enum.
5.3. Enum в интерфейсе
Аналогичным образом, мы можем объявить enum в интерфейсе:
interface HelloWorld { enum DIRECTIONS { NORTH, SOUTH, EAST, WEST; } }
Когда HelloWorld интерфейс компилятора добавит еще один классный файл под названием HelloWorld$Прямой.
5.4. Энум в пределах enum
Мы можем объявить enum внутри другого enum :
enum Foods { DRINKS, EATS; enum DRINKS { APPLE_JUICE, COLA; } enum EATS { POTATO, RICE; } }
Наконец, давайте посмотрим на генерируемые файлы класса:
Компилятор создает отдельный файл класса для каждого из enum Типы.
6. Заключение
В этой статье мы увидели различные конвенции именования, используемые для файлов класса Java. Мы добавили классы, интерфейсы и enums внутри одного файла Java и наблюдали, как компилятор создает отдельный файл класса для каждого из них.
Как всегда, примеры кода для этой статьи доступны более на GitHub .