13 авг. 2015 г.

Внутренние классы. Часть 1 – введение.

Все классы, которые мы рассматривали до сих пор являлись классами верхнего уровня (то есть они являлись непосредственными членами пакетов и не были вложены в другие классы). В интерфейсах, мы кратко рассмотрели тему вложенных интерфейсов. В Java есть четыре типа классов, именуемых внутренними или вложенными классами (inner or nested classes), которые могут быть определены в Java программе.

Примечание: Программисты, пишущие на Java, не пришли к единому мнению по поводу именования различных типов внутренних классов. Поэтому вы можете обнаружить, что в разных ситуациях их называют поразному. Например статические внутренние классы иногда называют вложенными – nested, а простые внутренние классы – inner. По крайней мере так они определяются в оригинальной документации, а так же многих книгах и руководствах.

Terminology: Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are called static nested classes. Non-static nested classes are called inner classes.

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

Внутренние классы являются элегантным и мощным инструментом языка Java. Эти четыре типа классов представлены ниже:

Статические вложенные классы (static nested classes)

Статический вложенный класс – это класс (или интерфейс), определенный как static внутри другого класса. Метод с модификатором static называют методом класса, поэтому внутренний класс такого типа можно назвать «классом класса», но подобная терминология была бы очень запутанной. Статические вложенные классы ведут себя почти так же, как обычные классы верхнего уровня, за исключением того, что они могут получать доступ к static членам класса, в котором они содержатся. Интерфейсы так же могут быть определены как статические внутренние члены классов.

Внутренние классы (inner classes)

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

Локальные классы (local classes)

Локальный класс – это класс, определенный в блоке Java-кода. Как и локальная переменная, локальный класс виден только внутри блока. Локальным классам присущи многие особенности внутренних классов. Кроме того, локальные классы могут работать с любыми final переменными или параметрами, которые доступны в блоке, где класс был определен. Интерфейсы нельзя определить локально.

Анонимные классы (anonymous classes)

Анонимный класс – это вид локального класса без имени; он комбинирует синтаксис для объявления класса с синтаксисом для присвоения значения объекту. Объявление локального класса – это оператор Java, а определение анонимного класса (и присвоение значения) – это выражение Java, поэтому такое определение может появляться только как часть еще большего выражения, например вызова метода. Интерфейсы нельзя определить анонимно.

Так же тут стоит упомянуть о том, что можно определить несколько классов верхнего уровня в одном файле .java. Такие классы не являются ни одним из типов внутренних классов. По существу это равнозначно что для каждого класса создается отдельный файл .java. Но если один .java файл содержит несколько классов верхнего уровня, только один из них может быть объявлен как public, остальные должны быть с пакетным доступом. И по имени класса public должен называться .java файл. Мы уже с этим встречались во множестве прошлых примеров кода, а тут я просто описал правило для этого случая. Обычно это используется для небольших тестовых или учебных программ, ну или для логической группировки связанных классов. Каждый класс верхнего уровня, который содержится в .java файле компилируется в отдельный .class файл с именем компилируемого класса. Приведу небольшой пример:

in01

Обратите внимание на подсветку скобок которые определяют границы класса Main. Класс Example не входит в эти границы и поэтому не является вложенным классом.

Если посмотреть на то файлы что сгенерировал компилятор, то мы увидим следующую картину:

in02

Далее уже будем рассматривать внутренние классы.

3 комментария:

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

    ОтветитьУдалить
    Ответы
    1. Извините, можно узнать к чему этот ваш комментарий? В данной статье, которая является вводной, я практически ни где не говорю об этом. И ни где тут не утверждаю, что из статических вложенных классов можно получить доступ к не статическим членам класса. Так что ваш комментарий мне не понятен.

      Удалить
  2. Прошу прощения, если что. Просто искал инфу именно по своим вопросам. А у Вас в разделе "статические вложенные классы" есть фраза про доступ. Еще раз перечитал: фраза правильная, но составлена не совсем удачно, поэтому я решил перефразировать. Можете мой коммент удалить, если считаете, что не в тему.

    ОтветитьУдалить