внешний класс java что
Вложенные и внутренние классы
Содержание
В этой главе мы обсудим внутренние классы Java.
Вложенные классы
В Java, подобно методам, переменные класса тоже могут иметь в качестве своего члена другой класс. В Java допускается написание класса внутри другого. Класс, написанный внутри, называется в Java вложенным классом, а класс, который содержит внутренний класс, называется внешним классом.
Синтаксис
Ниже приведен синтаксис для записи вложенного класса. Здесь класс Outer_Demo – это внешний класс, а класс Inner_Demo – вложенный класс.
Вложенные классы в Java делятся на два типа:
Внутренние классы (нестатические вложенные классы)
Внутренние классы — это механизм безопасности в Java. Мы уже знаем, что класс не может быть связан с модификатором доступа private, но если у нас есть класс как член другого класса, то внутренний класс может быть private. И это также используется для доступа к закрытым (private) членам класса.
В Java внутренние классы имеют три типа в зависимости от того, как и где Вы их определяете:
Внутренние классы
Создать внутренний класс в Java довольно просто. Вам просто нужно написать класс внутри класса. В отличие от класса, внутренний класс может быть закрытым (private), и после того, как Вы объявляете внутренний класс закрытым, он не может быть доступен из объекта вне класса.
Ниже приведен пример создания внутреннего класса и получения доступа к нему. В данном примере мы делаем внутренний класс private и получаем доступ к классу с помощью метода.
Пример
Здесь Вы можете заметить, что Outer_Demo – внешний класс, Inner_Demo – внутренний класс, display_Inner() – метод, внутри которого мы создаем внутренний класс, и этот метод вызывается из основного метода.
Если Вы скомпилируете и выполните вышеуказанную программу, Вы получите следующий результат:
Доступ к частным (private) членам
Как упоминалось ранее, внутренние классы также используются в Java для доступа к закрытым членам класса. Предположим, у класса есть private члены. Для доступа к ним напишите в нем внутренний класс, верните частные члены из метода внутри внутреннего класса, скажем, методом getValue() и, наконец, из другого класса (из которого Вы хотите получить доступ к закрытым членам) вызовите метод getValue() внутреннего класса.
Чтобы создать экземпляр внутреннего класса, сначала Вам необходимо создать экземпляр внешнего класса. После этого, используя объект внешнего класса, Вы можете создать экземпляр внутреннего класса.
Следующий пример показывает, как получить доступ к закрытым членам класса с использованием внутреннего класса.
Пример
Если Вы скомпилируете и выполняете вышеуказанную программу, то получите следующий результат:
Локальный метод внутреннего класса
В Java мы можем написать класс внутри метода, и это будет локальный тип. Как и локальные переменные, возможности внутреннего класса ограничены в рамках метода.
Локальный метод внутреннего класса может быть создан только внутри метода, где определяется внутренний класс. Следующая программа показывает, как использовать локальный внутренний метод.
Пример
Получим следующий результат:
Анонимные внутренние классы в Java
Анонимный внутренний класс — это внутренний класс, объявленный без имени класса. В случае анонимных внутренних классов в Java мы объявляем и создаем их в одно и то же время. Как правило, они используются всякий раз, когда Вам необходимо переопределить метод класса или интерфейса. Синтаксис анонимного внутреннего класса в Java выглядит следующим образом:
Синтаксис
Пример
Следующая программа показывает, как переопределить метод класса с использованием анонимного внутреннего класса.
Получим следующий результат:
Точно так же Вы можете переопределить методы конкретного класса, а также интерфейс, используя в Java анонимный внутренний класс.
Анонимный внутренний класс как аргумент
Как правило, если метод принимает объект интерфейса, абстрактный класс или конкретный класс, то мы можем реализовать интерфейс, расширить абстрактный класс и передать объект методу. Если это класс, мы можем напрямую передать его методу.
Но во всех трех случаях Вы можете в Java передать анонимный внутренний класс методу. Синтаксис передачи анонимного внутреннего класса в качестве аргумента метода:
Синтаксис
Пример
Следующая программа показывает, как передать анонимный внутренний класс в качестве аргумента метода.
Если Вы скомпилируете и выполните вышеуказанную программу, то получите следующий результат:
Статический вложенный класс в Java
Статический внутренний класс — это вложенный класс, который является статическим членом внешнего класса. Доступ к нему возможен без создания экземпляра внешнего класса с использованием других статических элементов. Как и статические члены, статический вложенный класс не имеет доступа к переменным экземпляра и методам внешнего класса. Синтаксис статического вложенного класса в Java выглядит следующим образом:
Синтаксис
Пример
Создание экземпляра статического вложенного класса немного отличается от экземпляра внутреннего класса. Следующая программа показывает, как использовать статические вложенные классы.
Получим следующий результат:
Внутренние и вложенные классы java. Часть 2
Внутренние и вложенные классы java. Часть 2
02.03.2017 — 2019 год
Inner Classes — Внутренние классы
Внутренний класс связан с экземпляром его обрамляющего класса (из документации).
Пример внутреннего класса есть в документации.
Так в чем же отличие, спросите вы. Объявления классов и вложенных и внутренних
одинаковые в данных случаях. Отличие в том, что внутренний класс связан с внешним классом через экземпляр, или через объект класса.
Чтобы создать экземпляр внутреннего класса, нам нужно сначала создать экземпляр внешнего класса. Затем создать внутренний объект, в пределах внешнего объекта, таким образом:
По-другому мы можем написать так:
Рассмотрим свойства внутренних классов.
Внутренние классы есть смысл использовать, если они будут использовать элементы родителя,
чтобы не передавать лишнего в конструкторах. Внутренний класс неявно наследуется от внешнего класса, хотя мы не используем ключевое слово extends в случае с классом или implements в случае с интерфейсом. То есть, во внутреннем классе мы можем использовать весь унаследованный функционал внешнего класса. Может показаться, что это сомнительно. Но это дает нам более гибкий подход. Таким образом мы можем использовать во внутреннем классе, функционал унаследованный от внешнего класса.
Внутренний класс стоит использовать, когда нам нужна инкапсуляция. Во внутреннем классе мы, таким образом закрываем всё от «внешнего мира».
Например, Map.Entry — нигде кроме интерфейса Map и его реализаций он не используется. Смотрите исходный код Map.Entry и Map. Это я привел только один пример.
Далее рассмотрим пример явного наследования.
В этом примере у нас, по сути, получилось множественное наследование, и мы можем использовать функционал класса AnyClass и функционал класса Outer6.
рис. 1
Здесь модификатор доступа у класса Outer6 по умолчанию. То есть класс Outer6 виден только в нашем пакете (package inner). Класс Inner6 закрыт от внешнего мира и внешнего воздействия.
То есть более «защищен».
Это только пример множественного наследования от «прилегающего» класса и класса «оболочки». На практике вам вряд-ли такое понадобится. Тут я рассматриваю такую возможность только в учебных целях и для лучшего понимания.
Замечание Выражение: «прилегающего» класса — взято из книги «Философия Java».
В этом примере видно, что мы можем использовать как поля и методы «окружающего» класса — Outer7, так поля и методы того класса, от которого мы наследовали внутренний класс — AnyClass2. Это дает нам несколько большие возможности и гибкость при использовании внутреннего класса. Хотя для множественного наследования более подходят интерфейсы.
Совет из книги «Философия Java. Брюс Эккель. ISBN 5-272-00250-4» c. 313:
«Каждый внутренний класс может независимо наследовать определенную реализацию.
Внутренний класс не ограничен при наследовании в ситуациях, где внешний класс уже наследует реализацию.»
Чтобы использовать внутренний класс, за пределами обычных методов «окружающего» класса необходимо создать объект внутреннего класса следующим способом.
ИмяВнешнегоКласса.ИмяВнутреннегоКласса.
Объект внутреннего класса сохраняет информацию о месте, где он был создан.
Майкл Морган. «Java 2.Руководство разработчика» ISBN 5-8459-0046-8
Брюс Эккель. «Философия Java.» ISBN 5-272-00250-4
Герберт Шилдт «Java. Полное руководство. 8-е издание.» ISBN: 978-5-8459-1759-1
Вложенные внутренние классы
Объект внутреннего класса не может существовать без объекта «внешнего» класса.
Это логично: для того мы и сделали Seat и HandleBar внутренними классами, чтобы в нашей программе не появлялись то тут, то там бесхозные рули и сиденья.
Этот код не скомпилируется:
Из этого вытекает следующая важная особенность:
У объекта внутреннего класса есть доступ к переменным «внешнего» класса.
Для примера давай добавим в наш класс Bicycle переменную int seatPostDiameter — диаметр подседельного штыря.
И теперь мы можем получить эту информацию в нашей программе:
Объект внутреннего класса нельзя создать в статическом методе «внешнего» класса.
Это объясняется особенностями устройства внутренних классов. У внутреннего класса могут быть конструкторы с параметрами или только конструктор по умолчанию. Но независимо от этого, когда мы создаем объект внутреннего класса, в него незаметно передается ссылка на объект «внешнего» класса. Ведь наличие такого объекта — обязательное условие. Иначе мы не сможем создавать объекты внутреннего класса.
Но если метод внешнего класса статический, значит, объект внешнего класса может вообще не существовать! А значит, логика работы внутреннего класса будет нарушена. В такой ситуации компилятор выбросит ошибку:
Внутренний класс не может содержать статические переменные и методы.
Логика здесь та же: статические методы и переменные могут существовать и вызваться даже при отсутствии объекта.
Но без объекта «внешнего» класса доступа к внутреннему классу у нас не будет.
Явное противоречие! Поэтому наличие статических переменных и методов во внутренних классах запрещено.
Компилятор выбросит ошибку при попытке их создать:
При создании объекта внутреннего класса важную роль играет его модификатор доступа.
Это влияет на то, где в нашей программе мы сможем создавать экземпляры внутреннего класса.
Кстати, мы уже это делали вот здесь:
Создать объект Seat снаружи мы уже не сможем:
Наверное, ты уже понял логику 🙂
Модификаторы доступа для внутренних классов работают так же, как и для обычных переменных.
Модификатор protected предоставляет доступ к переменной класса в его классах-наследниках и в классах, которые находятся в том же пакете.
Так же protected работает и для внутренних классов. Объекты protected внутреннего класса можно создавать:
Если у внутреннего класса нет модификатора доступа ( package private ), объекты внутреннего класса можно создавать
С модификаторами ты уже давно знаком, так что тут проблем не будет.
На этом пока все 🙂 Но не расслабляйся! Внутренние вложенные классы — довольно обширная тема, с которой мы продолжим знакомиться на следующих занятиях. Сейчас ты можешь освежить в памяти лекцию о внутренних классах из нашего курса. А в следующий раз поговорим о статических вложенных классах.
Внутренние и вложенные классы java. Часть 1
Внутренние и вложенные классы java. Часть 1
02.03.2017 — 2019 год
Цель статьи: Рассказать о внутренних, вложенных, локальных, анонимных классах. Показать примеры их использования. Написать и протестировать классы в коде на java. Рассказать о свойствах этих классов. Материал предназначен для лучшего понимания безымянных классов, лямбда выражений, адаптеров и многопоточности. То есть перед их изучением.
Небольшое вступление. Предлагаю вашему вниманию цикл из трех статей.
В них я рассказываю о внутренних, вложенных, локальных, анонимных классах. Речь идет о терминологии и применении. Для этих статей я написал довольно много кода.
Это учебный код, а не руководство к действию. То есть сам код я написал для лучшего понимания. Также я постарался объяснить работу учебного кода. На написание данной публикации, ушло довольно много времени. Публикация состоит из трех частей. Прошу отнестись с пониманием.
Для лучшего изучения материала у вас должна быть некоторая подготовка.
То есть вам нужно знать: синтаксис языка java, область видимости переменных, классы, статические и нестатические члены класса, создание экземпляров класса, наследование, модификаторы доступа.
Начнем с того, что же такое внутренние и вложенные классы. Посмотрим терминологию, встречающуюся в документации и литературе:
В Java существуют 4 типа вложенных (nested) классов:
Существуют четыре категории вложенных классов:
Попытаемся разобраться, что же это такое.
Начнем немного отдаленно, так как всё это имеет непосредственное отношение к нашим вопросам. Вспомним объектно-ориентированное программирование. Отношения композиции и наследования.
В своей книге «Java 2 Руководство разработчика» Майкл Морган очень хорошо и подробно описывает взаимосвязи классов и объектов. Мы рассмотрим некоторые из них. Взаимосвязь «это — есть — то» выражается наследованием, а взаимосвязь «имеет часть» описывается композицией.
В наших примерах мы в основном рассматриваем композицию. Так как вложенные классы — это и есть часть чего-то. То есть у нас есть класс оболочка и вложенный класс определенный внутри класса оболочки. Пример композиции: машина имеет двигатель, двери, 4 колеса, корпус. И мы можем описать машину с помощью внутренних (Inner) классов.
Пример такого использования вы можете найти в книге Брюса Эккеля «Философия Java»
Есть некоторое предупреждение автора по использованию кода в таком виде:
Так как композиция объекта является частью проведенного анализа задачи (а не
просто частью реализации класса), объявление членов класса открытыми, помогает программисту-клиенту понять, как использовать класс, и упрощает создателю написание кода. Однако нужно помнить, что описанный случай является особым, и в основном поля класса нужно объявлять как private.
Выше я не случайно упомянул наследование и композицию. Это напрямую относится к дальнейшему материалу.
Статические вложенные классы
Определение вложенных классов:
Класс называется вложенным (nested), если он определен внутри другого класса.
То есть класс просто определен внутри другого, даже не важно статически определен или не статически. Вложенный класс создается для того, чтобы обслуживать окружающий его класс. Если вложенный класс оказывается полезен в каком-либо ином контексте, он должен стать классом верхнего уровня.
Вложенные классы применяются в тех случаях, когда нужно написать небольшой вспомогательный код для другого класса. Вложенный класс создают также, чтобы скрыть его переменные и методы от внешнего мира. Таким образом, вложенный класс еще один элегантный способ ограничения области видимости. Внутренние классы также есть смысл использовать, если предполагается, что они будут использовать элементы родителя, чтобы не передавать лишнего в конструкторах.
Пример вложенного класса вы можете увидеть в документации Оракле:
У нас нет, пока что, никакого контекста использования данной конструкции. С таким же успехом вложенный класс мы можем назвать вместо: «Вложенный класс» (NestedClass) — «Внутренний класс» InnerClass. Далее будем разбираться, в чем же отличия, и в каких контекстах используются классы. Брюс Эккель пишет в книге «Философия Java» так:
«Класс называется вложенным (nested), если он определен внутри другого класса»
Документацию Oracle вы можете посмотреть по этой ссылке: >>>
Существует четыре категории вложенных классов:
Причины использования вложенных классов такие. Если класс полезен только для одного другого класса, то вполне логично встроить его в этот класс и хранить их вместе. Использование вложенных классов увеличивает инкапсуляцию. Рассмотрим два класса верхнего уровня, A и B, где B нужен доступ к членам, которые иначе были бы объявлены закрытыми.
Скрывая класс «B» в пределах класса «А», члены класса «А» могут быть объявлены закрытыми, и «B» может получить доступ к ним. Кроме того, сам «B» может быть скрыт от внешнего мира.
Продемонстрируем это в коде:
Использование вложенных классов приводит к более читабельному и поддерживаемому коду: Размещение класса ближе к тому месту, где он будет использован, делает код более читабельным.
Статические Вложенные Классы
Static Nested Classes
Причины использования статических вложенных классов такие.
Для случая, когда связь между объектом вложенного класса и объектом внешнего класса не нужна, можно сделать вложенный класс статическим(static).
Так как внутренний класс связан с экземпляром, он не может определить в себе любые статические члены.
Статические вложенные классы не имеют ограничений по объявлению своих данных и полей как static.
Из вложенного статического класса мы не имеем доступа к внешней не статической переменной внешнего класса.
Приведенный ниже код демонстрирует это:
Вывод: Мы не имеем доступа к не статическому полю внешнего класса, через статический контекст вложенного класса. Это подобно тому, как мы не имеем доступа из статического метода к нестатическим переменным класса. Точно также из статического вложенного класса мы не имеем доступа к нестатическим переменным внешнего класса.
Но мы имеем доступ к приватным статическим полям внешнего класса из вложенного статичного класса.
Приведенный ниже фрагмент кода демонстрирует это:
В этом примере кода мы создали экземпляр внутреннего класса с именем «nestedObj».
То есть мы получаем доступ к приватной статической переменной внешнего класса, через экземпляр внутреннего класса. В контексте экземпляра связанного с внешним классом, у нас получился внутренний класс.
Майкл Морган. «Java 2. Руководство разработчика» ISBN 5-8459-0046-8
Брюс Эккель. «Философия Java.» ISBN 5-272-00250-4
Герберт Шилдт «Java. Полное руководство. 8-е издание.» ISBN: 978-5-8459-1759-1
Все вопросы, комментарии, дополнения, критика приветствуются.
Продолжение следует…
Часть 2 >>>
Если у вас есть возможность, вам пригодилось, и вы можете помочь, то нажмите кнопку поддержать автора материально.
Вложенные и внутренние классы
Определение класса может размещаться внутри определения другого класса. Такие классы принято называть вложенными или внутренними. Область видимости вложенного класса ограничена областью видимости внешнего класса. Поэтому, если создается класс B внутри класса A, то класс B не может существовать независимо от класса A. Вложенные классы позволяют группировать классы, логически принадлежащие друг другу, и управлять доступом к ним.
Вложенные классы, nested classes
Если связь между объектом внутреннего класса и объектом внешнего класса не нужна, можно сделать внутренний класс статическим static. Такой класс называют вложенным nested. Применение статического внутреннего класса означает следующее :
Вложенный класс имеет доступ к членам своего внешнего класса, в том числе и к закрытым членам. Однако, внешний класс не имеет доступа к членам вложенного класса. Вложенный класс при этом является членом внешнего класса.
Статический класс объявляется ключевым словом static. При этом класс должен обращаться к нестатическим членам своего внешнего класса при помощи объекта, т.е. он не может обращаться напрямую на нестатические члены своего внешнего класса. На практие подобные классы используются редко.
Внутренние классы, inner classes
Нестатические вложенные классы называют также внутренними классами inner class. Внутренний класс имеет доступ ко всем переменным и методам своего внешнего класса и может непосредственно ссылаться на них. Внутренние классы создаются внутри окружающего класса :
Внутренний класс Inner определён в области видимости класса Outer. Поэтому любой код в классе Inner может непосредственно обращаться к переменным x1, x2 внешнего класса. После создания экземпляра класса Outer вызывается его метод summa () с параметрами, который создаёт экземпляр класса Inner с вызовом метода display ().
Внутренний класс можно определить не только на уровне класса, но и внутри метода или внутри тела цикла. Если понадобится создать объект внутреннего класса не в статическом методе внешнего класса, тип этого объекта должен задаваться в формате ИмяВнешнегоКласса.ИмяВнутреннегоКласса.
Объект внутреннего класса связан с внешним объектом-создателем и может обращаться к его членам без каких-либо дополнительных описаний. Для внутренних классов доступны все элементы внешнего класса. Если необходимо получить ссылку на объект внешнего класса, то следует использовать наименование внешнего класса с ключевым словом this, разделенных точкой, например : Outer.this.
Статические внутренние классы
Статические внутренние классы декларируются внутри основного класса и обозначаются ключевым словом static. Они не имеют доступа к членам внешнего класса за исключением статических.
Статический внутренний класс может содержать статические поля, методы и классы, в отличие от других типов внутренних классов. Пример :
Локальные классы
Локальный класс можно объявить внутри любого блока операторов. Например, внутри методов, циклов или операторов if. В следующем примере, проверяющем правильность телефонных номеров, объявляется локальный класс PhoneNumber в методе validatePhoneNumber :
Данная программа проверяет телефонные номера на соответствие некоторому стандарту. Сперва из номера удаляются все символы, отличные от цифр (0-9). После, происходит проверка длины номера и, если номер состоит из 10 цифр, то номер корректный. Данный пример выведет :
У локальных классов есть несколько ограничений :
Анонимные классы, anonymous class
Анонимные классы широко используются Java-программистами. Анонимный класс не имеют имени. Классический пример анонимного класса:
На основании анонимного класса создается поток и запускается с помощью метода start класса Thread. Синтаксис создания анонимного класса базируется на использовании оператора new с именем класса (интерфейса) и телом новосозданного анонимного класса.
Так как анонимный класс является локальным классом, он имеет все те же ограничения, что и локальный класс.
Использование анонимных классов оправдано во многих случаях, в частности когда: