Java internal classes
1. Meaning
In the Java programming language, programs are built from classes. Classes can also be declared inside a class, and we call such a class inner class.
2. Function
• Implementing better encapsulation, we know that access modifiers for ordinary classes (non-inner classes) cannot be private or protected, while inner classes can. When we declare the inner class as private, only the outer class can access the inner class, hiding the inner class nicely.
•Inner classes can inherit (extends) or implement (implements) other classes or interfaces without being affected by external classes.
•Inner classes can directly access fields and methods of external classes, even if they are modified with private. On the contrary, external classes cannot directly access members of internal classes.
3. Principle
Internal classes are a compile-time concept. After compilation, two independent class files will be generated, as follows:
public class Outer{ private String outerName = "outer"; class Inner{ private String innerName = "inner"; } }The compiled file is as follows:
After compilation, Outer.Inner is renamed to Outer$Inner, and the period (.) is replaced with the dollar sign ($).
IV. Classification
Java internal classes can be divided into member internal classes, local internal classes, anonymous internal classes, and static internal classes.
1) Internal class of members
A member internal class can be regarded as a member of an external class. A static member cannot be declared in a member internal class, but the static final field is an exception. We know that when a class is loaded, static members will be initialized first. If the internal class of the member has static members, the inner class will be generated before the external class. The inner class serves the external class, and the inner class generated before the external class may be out of control. When instantiating a member inner class, the member inner class will hold a reference to the current object of the external class, so that members of the external class can be directly accessed in the member inner class, even if private is modified.
import static java.lang.System.out; public class Outer{ private String outerName = "outer"; //The external class cannot directly access members of the inner class, and needs to instantiate the inner class object private Inner inner = new Inner(); public class Inner{ private String innerName = "inner"; public void show(){ out.println(outerName); //You can directly access members of the outer class} } public void show(){ out.println(inner.innerName); inner.show(); } public static void main(String[] args){ Outer outer = new Outer(); outer.show(); //Instantiate the inner class Outer.Inner inner = outer.new Inner(); inner.show(); } }Running results:
inner
outer
outer
The reference to the external class object of the member internal class is composed of the name of the external class before this. This form is called
Limited-this, out.println(outerName) and out.println(Outer.this.outerName) are equivalent.
2) Local internal classes
The use of local inner classes is basically the same as that of member inner classes. It is just that the local inner classes are defined in the methods of the external class, just like local variables, and are not members of the external class. A local inner class is inaccessible outside the method, but its instances can be returned from the method and the instances will remain until they are no longer referenced. Local internal classes can also access local variables, method parameters, etc. of the method they are located. The limitation is that local variables or method parameters can only be accessed when declared as final.
import static java.lang.System.out; public class Outer{ private String outerName = "outer"; public void show(final String str){ //The method parameters are final type class Inner{ public void print(){ out.println(outerName+str); } } Inner inner = new Inner(); inner.print(); } public static void main(String[] args){ Outer outer = new Outer(); outer.show(":lalala"); } }Running results:
outer:lalala
3) Anonymous internal class
You can imagine anonymous internal classes as local internal classes without class names. Anonymous internal classes have the following characteristics:
1. Anonymous internal classes cannot have constructors. Anonymous internal classes do not have class names, so the constructor cannot be declared.
2. Anonymous internal classes must inherit or implement an interface. The type assigned to new is the supertype of anonymous class. Anonymous classes cannot have extendeds or implements clauses displayed, nor can they have any modifiers.
3. Anonymous internal classes are the same as members' internal classes and local internal classes, and static members cannot be declared.
import static java.lang.System.out; public class Outer{ private String outerName = "outer"; public void show(final String str){ new Inner(){ //Implement the Inner interface public void print(){ out.println(outerName+str); } }.print(); } public static void main(String[] args){ Outer outer = new Outer(); outer.show(":lalala"); } } interface Inner{ void print(); }Running results:
outer:lalala
4) Static internal class
Static inner class, also called nested classes in some books, requires the use of static modifiers when declaring it. Static inner class is different from the first three inner classes. Static inner class does not hold references to the current object of the outer class, so non-static members of the outer class cannot be accessed in the static inner class. It can be said that static inner class does not depend on the outer class.
import static java.lang.System.out; public class Outer{ private String outerName = "outer"; private static int id = 123; private Inner inner = new Inner(); public static class Inner{ public void print1(){ //out.println(outerName); Non-static member of the external class cannot be accessed out.println(id); } public static void print2(){ out.println(id); } } public void show(){ inner.print1(); } public static void main(String[] args){ Outer outer = new Outer(); outer.show(); Outer.Inner.print2(); //Turnly access the static inner class through the class name} }