Java Nested Classes
In Java nested classes are classes that are defined inside another class.
The purpose of a nested class is to clearly group the nested class with its surrounding class, signaling that these two classes are to be used together. Or perhaps that the nested class is only to be used from inside its enclosing (owning) class.
Java developers often refer to nested classes as inner classes, but inner classes (non-static nested classes) are only one out of several different types of nested classes in Java.
In Java nested classes are considered members of their enclosing class. Thus, a nested class can be declared public , package (no access modifier), protected and private (see access modifiers for more info). Therefore nested classes in Java can also be inherited by subclasses as explained in my tutorial about Java inheritance.
You can create several different types of nested classes in Java. The different Java nested class types are:
- Static nested classes
- Non-static nested classes
- Local classes
- Anonymous classes
All these types of nested classes will be covered in the following sections.
Static Nested Classes
Static nested classes are declared in Java like this:
In order to create an instance of the Nested class you must reference it by prefixing it with the Outer class name, like this:
Outer.Nested instance = new Outer.Nested();
In Java a static nested class is essentially a normal class that has just been nested inside another class. Being static, a static nested class can only access instance variables of the enclosing class via a reference to an instance of the enclosing class.
Non-static Nested Classes (Inner Classes)
Non-static nested classes in Java are also called inner classes. Inner classes are associated with an instance of the enclosing class. Thus, you must first create an instance of the enclosing class to create an instance of an inner class. Here is an example inner class definition:
Here is how you create an instance of the Inner class:
Outer outer = new Outer(); Outer.Inner inner = outer.new Inner();
Notice how you put new after the reference to the outer class in order to create an instance of the inner class.
Non-static nested classes (inner classes) have access to the fields of the enclosing class, even if they are declared private. Here is an example of that:
Notice how the printText() method of the Inner class references the private text field of the Outer class. This is perfectly possible. Here is how you would call the printText() method:
Outer outer = new Outer(); Outer.Inner inner = outer.new Inner(); inner.printText();
Inner Class Shadowing
If a Java inner class declares fields or methods with the same names as field or methods in its enclosing class, the inner fields or methods are said to shadow over the outer fields or methods. Here is an example:
In the above example both the Outer and Inner class contains a field named text . When the Inner class refers to text it refers to its own field. When Outer refers to text it also refers to its own field.
Java makes it possible though, for the Inner class to refer to the text field of the Outer class. To do so it has to prefix the text field reference with Outer.this. (the outer class name + .this. + field name) like this:
Now the Inner.printText() method will print both the Inner.text and Outer.text fields.
Local Classes
Local classes in Java are like inner classes (non-static nested classes) that are defined inside a method or scope block ( < . >) inside a method. Here is an example:
class Outer < public void printText() < class Local < >Local local = new Local(); > >
Local classes can only be accessed from inside the method or scope block in which they are defined.
Local classes can access members (fields and methods) of its enclosing class just like regular inner classes.
Local classes can also access local variables inside the same method or scope block, provided these variables are declared final .
From Java 8 local classes can also access local variables and parameters of the method the local class is declared in. The parameter will have to be declared final or be effectually final. Effectually final means that the variable is never changed after it is initialized. Method parameters are often effectually final.
Local classes can also be declared inside static methods. In that case the local class only has access to the static parts of the enclosing class. Local classes cannot contain all kinds of static declarations (constants are allowed — variables declared static final ), because local classes are non-static in nature — even if declared inside a static method.
The same shadowing rules apply for local classes as for inner classes.
Anonymous Classes
Anonymous classes in Java are nested classes without a class name. They are typically declared as either subclasses of an existing class, or as implementations of some interface.
Anonymous classes are defined when they are instantiated. Here is an example that declares an anonymous subclass of a superclass called SuperClass :
SuperClass instance = new SuperClass() < public void doIt() < System.out.println("Anonymous class doIt()"); >>; instance.doIt();
Running this Java code would result in Anonymous class doIt() being printed to System.out . The anonymous class subclasses (extends) SuperClass and overrides the doIt() method.
A Java anonymous class can also implement an interface instead of extending a class. Here an example:
public interface MyInterface
MyInterface instance = new MyInterface() < public void doIt() < System.out.println("Anonymous class doIt()"); >>; instance.doIt();
As you can see, an anonymous class implementing an interface is pretty similar to an anonymous class extending another class.
An anonymous class can access members of the enclosing class. It can also access local variables which are declared final or effectively final (since Java 8).
You can declare fields and methods inside an anonymous class, but you cannot declare a constructor. You can declare a static initializer for the anonymous class instead, though. Here is an example:
final Strint textToPrint = "Text. "; MyInterface instance = new MyInterface() < private String text; //static initializer < this.text = textToPrint; >public void doIt() < System.out.println(this.text); >>; instance.doIt();
The same shadowing rules apply to anonymous classes as to inner classes.
Nested Class Benefits
The benefits of Java nested classes are that you can group classes together that belong together. You could do so already by putting them in the same package, but putting one class inside another makes an even stronger grouping.
A nested class is typically only used by or with its enclosing class. Sometimes a nested class is only visible to the enclosing class, is only used internally, and is thus never visible outside the enclosing class. Other times the nested class is visible outside its enclosing class, but can only be used in conjunction with the enclosing class.
An example would be a Cache class. Inside the Cache class you might declare a CacheEntry class which can contain information about a specific cache entry (cached value, time inserted, number of times accessed etc.). Users of the Cache class may never see the CacheEntry class, if they have no need to obtain information about the CacheEntry itself, but only the cached value. However, the Cache class may choose to make the CacheEntry class visible to the outside world, so they can access more than just the cached value (for instance information about when the value was last refreshed etc.).
Here are two Cache implementation skeletons illustrating the points:
public class Cache < private MapcacheMap = new HashMap(); private class CacheEntry < public long timeInserted = 0; public object value = null; >public void store(String key, Object value) < CacheEntry entry = new CacheEntry(); entry.value = value; entry.timeInserted = System.currentTimeMillis(); this.cacheMap.put(key, entry); >public Object get(String key) < CacheEntry entry = this.cacheMap.get(key); if(entry == null) return null; return entry.value; >>
public class Cache < private MapcacheMap = new HashMap(); public class CacheEntry < public long timeInserted = 0; public object value = null; >public void store(String key, Object value) < CacheEntry entry = new CacheEntry(); entry.value = value; entry.timeInserted = System.currentTimeMillis(); this.cacheMap.put(key, entry); >public Object get(String key) < CacheEntry entry = this.cacheMap.get(key); if(entry == null) return null; return entry.value; >public CacheEntry getCacheEntry(String key) >
The first Cache class hides its CacheEntry nested class while the second Cache class exposes it.
Nested Classes in Java
In Java, it is possible to define a class within another class, such classes are known as nested classes. They enable you to logically group classes that are only used in one place, thus this increases the use of encapsulation, and creates more readable and maintainable code.
- The scope of a nested class is bounded by the scope of its enclosing class. Thus in below example, class NestedClass does not exist independently of class OuterClass.
- A nested class has access to the members, including private members, of the class in which it is nested. But the enclosing class does not have access to the member of the nested class.
- A nested class is also a member of its enclosing class.
- As a member of its enclosing class, a nested class can be declared private, public, protected, or package private(default).
- Nested classes are divided into two categories:
- static nested class : Nested classes that are declared static are called static nested classes.
- inner class : An inner class is a non-static nested class.
Static nested classes
In the case of normal or regular inner classes, without an outer class object existing, there cannot be an inner class object. i.e., an object of the inner class is always strongly associated with an outer class object. But in the case of static nested class, Without an outer class object existing, there may be a static nested class object. i.e., an object of a static nested class is not strongly associated with the outer class object.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.They are accessed using the enclosing class name.
OuterClass.StaticNestedClass
For example, to create an object for the static nested class, use this syntax:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
Creating nested class java
Объясните кто знает что за модификатора доступа (package private)? Чем он отличается от обычного private? Могу предположить что автор имел ввиду default access modifier, поправьте если не прав.
Продолжение про нестатические вложенные (анонимные) классы (2/3 часть): https://javarush.com/groups/posts/2193-anonimnihe-klassih Продолжение про статические вложенные классы (3/3 часть): https://javarush.com/groups/posts/2183-staticheskie-vlozhennihe-klassih
Зачем давать не актуальную информацию? Внутренний класс МОЖЕТ содержать статические переменные и методы но с JAVA 16.
В шестом пункте написано » Если у внутреннего класса нет модификатора доступа (package private), объекты внутреннего класса можно создавать внутри «внешнего» класса;» , а если есть, то нельзя?
Так же protected работает и для внутренних классов. Объекты protected внутреннего класса можно создавать: внутри «внешнего» класса; в его классах-наследниках; в тех классах, которые находятся в том же пакете. Может кто подсказать, что за хрень творится с этим модификатором доступа? Почему я не могу создать экземпляр внутреннего класса в классе-наследнике (наследование от внешнего класса, так как от внутреннего protected компилятор не дает наследоваться) в другом пэкадже? Хотя в статье говориться, что я могу это сделать.
Вообще не понимаю что тут написано 🤷🏽♂️ «Объект внутреннего класса нельзя создать в статическом методе «внешнего» класса. Это объясняется особенностями устройства внутренних классов. У внутреннего класса могут быть конструкторы с параметрами или только конструктор по умолчанию. Но независимо от этого, когда мы создаем объект внутреннего класса, в него незаметно передается ссылка на объект «внешнего» класса. Ведь наличие такого объекта — обязательное условие. Иначе мы не сможем создавать объекты внутреннего класса. Но если метод внешнего класса статический, значит, объект внешнего класса может вообще не существовать! А значит, логика работы внутреннего класса будет нарушена. В такой ситуации компилятор выбросит ошибку:
public static Seat createSeat() < //Bicycle.this cannot be referenced from a static context return new Seat(); >
Объект внутреннего класса нельзя создать в статическом методе «внешнего» класса. Может быть его нельзя создать не потому что есть или нет объекта внешнего класса, который можно создать по дефолту, а потому что в статических методах нельзя использовать нестатические переменные? public class Main < public static void main(String[] args) < Outer obj = new Outer(); Outer.Inner obj1 = obj.getObj(); System.out.println(obj1.a); >> class Outer < static class Inner < int a = 5; >static Inner getObj() < return new Inner(); >>