Nested Classes
The Java programming language allows you to define a class within another class. Such a class is called a nested class and is illustrated here:
A nested class is a member of its enclosing class. Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private. Static nested classes do not have access to other members of the enclosing class. As a member of the OuterClass , a nested class can be declared private , public , protected , or package private. (Recall that outer classes can only be declared public or package private.)
Why Use Nested Classes?
Compelling reasons for using nested classes include the following:
It is a way of logically grouping classes that are only used in one place: If a class is useful to only one other class, then it is logical to embed it in that class and keep the two together. Nesting such "helper classes" makes their package more streamlined.
It increases encapsulation: Consider two top-level classes, A and B, where B needs access to members of A that would otherwise be declared private . By hiding class B within class A, A's members can be declared private and B can access them. In addition, B itself can be hidden from the outside world.
It can lead to more readable and maintainable code: Nesting small classes within top-level classes places the code closer to where it is used.
Inner Classes
As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.
Objects that are instances of an inner class exist within an instance of the outer class. Consider the following classes:
An instance of InnerClass can exist only within an instance of OuterClass and has direct access to the methods and fields of its enclosing instance.
To instantiate an inner class, you must first instantiate the outer class. Then, create the inner object within the outer object with this syntax:
There are two special kinds of inner classes: local classes and anonymous classes.
Static Nested Classes
As with class methods and variables, a static nested class is associated with its outer class. And like static class methods, a static nested class cannot refer directly to instance variables or methods defined in its enclosing class: it can use them only through an object reference. Inner Class and Nested Static Class Example demonstrates this.
You instantiate a static nested class the same way as a top-level class:
Inner Class and Nested Static Class Example
The following example, OuterClass , along with TopLevelClass , demonstrates which class members of OuterClass an inner class ( InnerClass ), a nested static class ( StaticNestedClass ), and a top-level class ( TopLevelClass ) can access:
OuterClass.java
TopLevelClass.java
This example prints the following output:
Note that a static nested class interacts with the instance members of its outer class just like any other top-level class. The static nested class StaticNestedClass can’t directly access outerField because it’s an instance variable of the enclosing class, OuterClass . The Java compiler generates an error at the highlighted statement:
To fix this error, access outerField through an object reference:
Similarly, the top-level class TopLevelClass can’t directly access outerField either.
Note: For more information about the taxonomy of the different kinds of classes in the Java programming language (which can be tricky to describe concisely, clearly, and correctly), see Joseph Darcy's blog: Nested, Inner, Member, and Top-Level Classes.
Shadowing
If a declaration of a type (such as a member variable or a parameter name) in a particular scope (such as an inner class or a method definition) has the same name as another declaration in the enclosing scope, then the declaration shadows the declaration of the enclosing scope. You cannot refer to a shadowed declaration by its name alone. The following example, ShadowTest , demonstrates this:
The following is the output of this example:
This example defines three variables named x : the member variable of the class ShadowTest , the member variable of the inner class FirstLevel , and the parameter in the method methodInFirstLevel . The variable x defined as a parameter of the method methodInFirstLevel shadows the variable of the inner class FirstLevel . Consequently, when you use the variable x in the method methodInFirstLevel , it refers to the method parameter. To refer to the member variable of the inner class FirstLevel , use the keyword this to represent the enclosing scope:
Serialization of inner classes, including local and anonymous classes, is strongly discouraged. When the Java compiler compiles certain constructs, such as inner classes, it creates synthetic constructs; these are classes, methods, fields, and other constructs that do not have a corresponding construct in the source code. Synthetic constructs enable Java compilers to implement new Java language features without changes to the JVM. However, synthetic constructs can vary among different Java compiler implementations, which means that .class files can vary among different implementations as well. Consequently, you may have compatibility issues if you serialize an inner class and then deserialize it with a different JRE implementation. See the section Implicit and Synthetic Parameters in the section Obtaining Names of Method Parameters for more information about the synthetic constructs generated when an inner class is compiled.
Вложенные классы java для чего нужны

Классы могут быть вложенными (nested), то есть могут быть определены внутри других классов. Частным случаем вложенных классов являются внутренние классы (inner class). Например, имеется класс Person, внутри которого определен класс Account:
Внутренний класс ведет себя как обычный класс за тем исключением, что его объекты могут быть созданы только внутри внешнего класса.
Внутренний класс имеет доступ ко всем полям внешнего класса, в том числе закрытым с помощью модификатора private. Аналогично внешний класс имеет доступ ко всем членам внутреннего класса, в том числе к полям и методам с модификатором private.
Ссылку на объект внешнего класса из внутреннего класса можно получить с помощью выражения Внешний_класс.this , например, Person.this .
Объекты внутренних классов могут быть созданы только в том классе, в котором внутренние классы опеределены. В других внешних классах объекты внутреннего класса создать нельзя.
Еще одной особенностью внутренних классов является то, что их можно объявить внутри любого контекста, в том числе внутри метода и даже в цикле:
Статические вложенные классы
Кроме внутренних классов также могут быть статические вложенные классы. Статические вложенные классы позволяют скрыть некоторую комплексную информацию внутри внешнего класса:
Здесь определен вложенный класс для хранения данных о вычислении факториала. Основные действия выполняет метод getFactorial , который возвращает объект вложенного класса. И теперь используем классы в методе main:
Внутренние и вложенные классы java. Часть 1

Цель статьи: Рассказать о внутренних, вложенных, локальных, анонимных классах. Показать примеры их использования. Написать и протестировать классы в коде на java. Рассказать о свойствах этих классов. Материал предназначен для лучшего понимания безымянных классов, лямбда выражений, адаптеров и многопоточности. То есть перед их изучением.
Небольшое вступление. Предлагаю вашему вниманию цикл из трех статей.
В них я рассказываю о внутренних, вложенных, локальных, анонимных классах. Речь идет о терминологии и применении. Для этих статей я написал довольно много кода.
Это учебный код, а не руководство к действию. То есть сам код я написал для лучшего понимания. Также я постарался объяснить работу учебного кода. На написание данной публикации, ушло довольно много времени. Публикация состоит из трех частей. Прошу отнестись с пониманием.
Для лучшего изучения материала у вас должна быть некоторая подготовка.
То есть вам нужно знать: синтаксис языка java, область видимости переменных, классы, статические и нестатические члены класса, создание экземпляров класса, наследование, модификаторы доступа.
Начнем с того, что же такое внутренние и вложенные классы. Посмотрим терминологию, встречающуюся в документации и литературе:
В Java существуют 4 типа вложенных (nested) классов:
- Статические вложенные классы
- Внутренние классы
- Локальные классы
- Анонимные (безымянные) классы
Существуют четыре категории вложенных классов:
- статический класс-член (static member class),
- не статический класс-член (nonstatic member class),
- анонимный класс (anonymous class)
- и локальный класс (local class).
Попытаемся разобраться, что же это такое.
Начнем немного отдаленно, так как всё это имеет непосредственное отношение к нашим вопросам. Вспомним объектно-ориентированное программирование. Отношения композиции и наследования.
В своей книге «Java 2 Руководство разработчика» Майкл Морган очень хорошо и подробно описывает взаимосвязи классов и объектов. Мы рассмотрим некоторые из них. Взаимосвязь «это — есть — то» выражается наследованием, а взаимосвязь «имеет часть» описывается композицией.
В наших примерах мы в основном рассматриваем композицию. Так как вложенные классы — это и есть часть чего-то. То есть у нас есть класс оболочка и вложенный класс определенный внутри класса оболочки. Пример композиции: машина имеет двигатель, двери, 4 колеса, корпус. И мы можем описать машину с помощью внутренних (Inner) классов.
Пример такого использования вы можете найти в книге Брюса Эккеля «Философия Java»
Есть некоторое предупреждение автора по использованию кода в таком виде:
Выше я не случайно упомянул наследование и композицию. Это напрямую относится к дальнейшему материалу.
Статические вложенные классы
Определение вложенных классов:
То есть класс просто определен внутри другого, даже не важно статически определен или не статически. Вложенный класс создается для того, чтобы обслуживать окружающий его класс. Если вложенный класс оказывается полезен в каком-либо ином контексте, он должен стать классом верхнего уровня.
Вложенные классы применяются в тех случаях, когда нужно написать небольшой вспомогательный код для другого класса. Вложенный класс создают также, чтобы скрыть его переменные и методы от внешнего мира. Таким образом, вложенный класс еще один элегантный способ ограничения области видимости. Внутренние классы также есть смысл использовать, если предполагается, что они будут использовать элементы родителя, чтобы не передавать лишнего в конструкторах.
Пример вложенного класса вы можете увидеть в документации Оракле:
У нас нет, пока что, никакого контекста использования данной конструкции. С таким же успехом вложенный класс мы можем назвать вместо: «Вложенный класс» (NestedClass) — «Внутренний класс» InnerClass. Далее будем разбираться, в чем же отличия, и в каких контекстах используются классы. Брюс Эккель пишет в книге «Философия Java» так:
Документацию Oracle вы можете посмотреть по этой ссылке: >>>
Терминология:
Существует четыре категории вложенных классов:
- Статические вложенные классы и не статические вложенные классы. Вложенные классы, объявленные статически, называются вложенными статическими классами.
- Внутренние классы — когда объект внутреннего класса связан с объектом обрамляющего класса. Не статические вложенные классы называются внутренними классами, если они связанны с внешним классом.
- Локальные классы — объявленные внутри блока кода и не являющиеся членом обрамляющего класса. В этом случае можно рассматривать класс как локальную переменную типа класс.
- Анонимные классы – наследуемые, от какого либо класса, классы в которых при объявлении не задано имя класса.
Причины использования вложенных классов такие. Если класс полезен только для одного другого класса, то вполне логично встроить его в этот класс и хранить их вместе. Использование вложенных классов увеличивает инкапсуляцию. Рассмотрим два класса верхнего уровня, A и B, где B нужен доступ к членам, которые иначе были бы объявлены закрытыми.
Скрывая класс «B» в пределах класса «А», члены класса «А» могут быть объявлены закрытыми, и «B» может получить доступ к ним. Кроме того, сам «B» может быть скрыт от внешнего мира.
Продемонстрируем это в коде:
Использование вложенных классов приводит к более читабельному и поддерживаемому коду: Размещение класса ближе к тому месту, где он будет использован, делает код более читабельным.
Статические Вложенные Классы
Static Nested Classes
Причины использования статических вложенных классов такие.
Для случая, когда связь между объектом вложенного класса и объектом внешнего класса не нужна, можно сделать вложенный класс статическим(static).
Так как внутренний класс связан с экземпляром, он не может определить в себе любые статические члены.
Статические вложенные классы не имеют ограничений по объявлению своих данных и полей как static.
Из вложенного статического класса мы не имеем доступа к внешней не статической переменной внешнего класса.
Приведенный ниже код демонстрирует это:
Вывод: Мы не имеем доступа к не статическому полю внешнего класса, через статический контекст вложенного класса. Это подобно тому, как мы не имеем доступа из статического метода к нестатическим переменным класса. Точно также из статического вложенного класса мы не имеем доступа к нестатическим переменным внешнего класса.
Но мы имеем доступ к приватным статическим полям внешнего класса из вложенного статичного класса.
Приведенный ниже фрагмент кода демонстрирует это:
Все вопросы, комментарии, дополнения, критика приветствуются.
Продолжение следует…
Часть 2 >>>
Если у вас есть возможность, вам пригодилось, и вы можете помочь, то нажмите кнопку поддержать автора материально.
Для чего в java нужны вложенные классы?
Нестатические вложенные классы (non static nested classes)
Они же — внутренние классы.
Где применяется?
Там где вы описываете структуру будущего объекта, который имеет не только состояние и поведение, но и имеет какие-то дополнительные (составные) части. Без которых сам объект не существовал бы.
Например, машина. Смысл от нее теряется, если она стоит во дворе на кирпичах, а колеса от нее лежат в гараже, а вам нужно сесть и поехать. В таком случае вам придется потратить время, чтобы взять машину, взять домкрат, взять колеса и проделать все действия по их установке.
Как применяется?
Внутренний класс имеет доступ через методы ко всем полям и методам внешнего класса и может ссылаться к ним напрямую. Но внешний класс может обращаться к методам и полям внутреннего только по ссылке. Выглядит это так:
Или чтобы из метода main вызвать напрямую метод внутреннего класса, мы может сделать это так:
Внутренний класс так же можно определять внутри методов и циклов.
Статические вложенные классы (static nested classes)
Первое, что нужно понимать, что вложенные классы в отличии от внутренних помечаются ключевым словом static . И чтобы во вложенном классе можно было работать с методами и полями внешнего класса, они тоже должны быть помечены static .
Где применяется?
Ну, возьмем для примера ситуацию, когда Петя идет в школу с портфелем, а Машенька без, т.е. несет учебники на руках. Тут Петя может сказать — «Слушай, я могу поделиться своим портфелем, ты клади в него свои учебники, все равно мне его нести. «. То есть Машенька положит свои учебники в портфель Пети, потому что Петя не жадный, он поделится.
Как применяется?
Все обращения к полям и методам внешнего класса и наоборот к полям и методам вложенного класса происходит через класс.
![]()
Постараюсь объяснить максимально просто:
В основном в java внутренние классы служат нам для того, чтобы привязывать одну сущность к другой. Например: сущность МАШИНА , у него есть руль , коробка передач , педали . И зачем создавать публичные классы со всем этим? Просто кинул как внутренний в класс Машина и вот лафа.
Так же удобно для применения всяких патернов типа singleton и builder .
![]()
Обычно внутренний класс наследует от класса или реализует интерфейс, а код внутреннего класса манипулирует объектом внешнего класса, в котором он был создан. Значит, можно сказать, что внутренний класс —это нечто вроде «окна» во внешний класс.
Возникает естественный вопрос: «Если мне нужна ссылка на интерфейс, почему бы внешнему классу не реализовать этот интерфейс?» Ответ здесь таков: «Если это все, что вам нужно, —значит, так и следует поступить». Но что же отличает внутренний класс, реализующий интерфейс, от внешнего класса, реализующего тот же интерфейс? Далеко не всегда удается использовать удобство интерфейсов —иногда приходится работать и с реализацией. Поэтому наиболее веская причина для использования внутренних классов формулируется так:
Каждый внутренний класс способен независимо наследовать определенную реализацию. Таким образом, внутренний класс не ограничен при наследовании в ситуациях, где внешний класс уже наследует реализацию.
Без способности внутренних классов наследовать (фактически) реализацию более чем одного конкретного или абстрактного класса некоторые задачи планирования и программирования имели бы крайне сложное решение. Поэтому внутренний класс выступает как «довесок» множественного наследования. Интерфейсы берут на себя часть этой задачи, в то время как внутренние классы фактически обеспечивают «множественное наследование реализации». То есть внутренние классы позволяют вам наследовать от нескольких «не-интерфейсов».
Чтобы понять сказанное, рассмотрим ситуацию, где два интерфейса тем или иным способом должны быть реализованы в классе. Вследствие гибкости интерфейсов у вас есть два варианта: одиночный класс или внутренний класс:
Конечно, выбор того или иного способа организации кода зависит от конкретной ситуации. Впрочем, сама решаемая вами задача должна подсказать, что для нее пред почтительно: один отдельный класс или внутренний класс. Но при отсутствии иных ограничений оба подхода, использованные в рассмотренном примере, ничем не от личаются с точки зрения реализации. Оба они работают. Однако, если вместо интерфейсов у вас имеются конкретные или абстрактные классы, придется «звать на помощь» внутренние классы, если новый класс должен как-то за действовать функциональность двух других классов:
Если вам не приходится решать задачу «множественного наследования реализации», скорее всего, вы сможете написать любую программу без использования особенностей внутренних классов. С другой стороны, внутренние классы открывают следующие дополнительные возможности.
У внутреннего класса может существовать произвольное количество экземпляров, каждый из которых содержит собственную информацию, не зависящую от состояния объекта внешнего класса.
Один внешний класс может содержать несколько внутренних классов, которые по-разному реализуют один интерфейс или наследуют от единственного базового класса. Пример такой конструкции вскоре будет рассмотрен.
Место создания объекта внутреннего класса не привязано к месту и времени создания объекта внешнего класса.
Внутренний класс не создает взаимосвязи классов типа «является тем-то», способной вызвать путаницу; он представляет собой отдельную сущность.