В качестве типа
переменной в Java может использоваться одна из пяти сущностей:
1. примитивный тип;
2. class – сложный тип, с поведением (API), возможно его реализацией и внутренним состоянием;
3. enum – перечисление. Тип с заданным конечным набором возможных значений;
4. interface – только описание поведения, без состояния. С Java 8 может иметь дефолтную реализацию. Возможно множественное наследование интерфейсов;
5. @interface – аннотация. Пассивная метаинформация уровня класса: само ее наличие, параметры и поведение. Обычно используется для описания особых свойств (
@Deprecated), для использования фреймворками (
@Test) или инструментами разработки (
@NotNull);
Новые примитивы создавать
пока нельзя. Остальные типы называются ссылочными – переменная несет не значение, а ссылку на экземпляр. Для каждого ссылочного типа при компиляции создается отдельный
.class
файл. Его содержимое рассмотрим позднее.
Теме посвящена
глава 8 спецификации.
Класс бывает:
1. Абстрактный – помеченный ключевым словом
abstract
. Не может иметь экземпляры, может иметь нереализованные абстрактные методы, также с модификатором
abstract
и без тела. Похож на частично реализованный интерфейс с состоянием, хотя с точки зрения JVM это
совсем другая сущность;
2. Внутренний (inner, non-static nested) – объявленный внутри другого класса. Не может иметь статических объявлений. Имеет доступ ко всем внутренностям
экземпляра внешнего класса. Если член внешнего класса
foo
перекрыт членом внутреннего (shadowing), обратиться к внешнему можно с помощью конструкции
OuterClassname.this.foo
, без перекрытия сработает просто
foo
. Инстанциируется только от экземпляра внешнего класса:
outer.new Inner()
;
3. Вложенный (nested, inner static) – имеет доступ ко всем статическим членам внешнего класса. В остальном ничем не отличается от обычного класса;
4. Локальный – объявленный внутри метода. Является внутренним классом, в случае объявления в статическом методе без доступа к экземпляру внешнего класса. Не имеет модификаторов доступа;
5. Анонимный – локальный класс, объявленный без имени, непосредственно при инстанциировании, расширением другого класса или интерфейса. В отличие от других вложенных классов, анонимный может расширять только один класс или интерфейс. Не может быть абстрактным или финальным. Лямбда-выражение является сокращенной записью создания объекта анонимного наследника
функционального интерфейса;
6. Финальный – с модификатором
final
,
нерасширяемый;
Внутренние и вложенные классы могут иметь несколько уровней вложенности. Модификаторы abstract и final несовместимы, но по отдельности применимы к различным внутренним классам (кроме анонимного). Подробно разные виды вложенных классов рассмотрены в
официальном туториале.