Summary of Inner Classes in Java
Category Programming Techniques
Inner classes are not easy to understand, but in essence, they are just a class within another class.
Like a person composed of brain, limbs, organs, etc., an inner class is akin to one of those organs, such as the heart: it has its own attributes and behaviors (blood, beating).
Clearly, a heart cannot be represented solely by attributes or methods; it requires a class.
And the heart is within the human body, just as an inner class is within an outer class.
Example 1: Basic Structure of Inner Classes
// Outer class
class Out {
private int age = 12;
// Inner class
class In {
public void print() {
System.out.println(age);
}
}
}
public class Demo {
public static void main(String[] args) {
Out.In in = new Out().new In();
in.print();
// Or access using this method
/*
Out out = new Out();
Out.In in = out.new In();
in.print();
*/
}
}
Output: 12
From the example above, it's clear that inner classes severely disrupt the structure of good code. So why use them?
Because inner classes can freely use the member variables of the outer class (including private ones) without creating an instance of the outer class. This is the only advantage of inner classes.
Like the heart directly accessing the body's blood, rather than through a doctor drawing blood.
After compiling, two .class files will be generated: Out.class and Out$In.class.
The $ represents the Out.In in the program above.
Out.In in = new Out().new In()
can be used to create an object of the inner class. There are two small points to note:
- The initial Out indicates which outer class the inner class object belongs to.
- An object of the outer class must exist before an object of the inner class can be created, because the purpose of the inner class is to access the member variables of the outer class.
class Out { private int age = 12; class In { private int age = 13; public void print() { int age = 14; System.out.println("Local variable: " + age); System.out.println("Inner class variable: " + this.age); System.out.println("Outer class variable: " + Out.this.age); } } } public class Demo { public static void main(String[] args) { Out.In in = new Out().new In(); in.print(); } }
- An object of the outer class must exist before an object of the inner class can be created, because the purpose of the inner class is to access the member variables of the outer class.
Output:
Local variable: 14
Inner class variable: 13
Outer class variable: 12
From Example 1, it can be seen that if there are no member variables with the same name and local variables in the inner class, the inner class will directly access the member variables of the outer class without specifying Out.this.attributeName
.
Otherwise, the local variable in the inner class will override the member variable of the outer class.
To access the member variables of the inner class itself, use this.attributeName
, and to access the member variables of the outer class, use Out.this.attributeName
.
Example 3: Static Inner Class
class Out {
private static int age = 12;
static class In {
public void print() {
System.out.println(age);
}
}
}
public class Demo {
public static void main(String[] args) {
Out.In in = new Out.In();
in.print();
}
}
Output: 12
As seen, if the inner class is static, it can only access the static member variables of the outer class, which is limiting.
Secondly, because the inner class is static, Out.In can be treated as a whole and an object of the inner class can be directly created (accessing static through the class name, whether or not an object of the outer class is created is irrelevant).
Example 4: Private Inner Class
class Out {
private int age = 12;
private class In {
public void print() {
System.out.println(age);
}
}
public void outPrint() {
new In().print();
}
}
public class Demo {
public static void main(String[] args) {
// This method is invalid
/*
Out.In in = new Out().new In();
in.print();
*/
Out out = new Out();
out.outPrint();
}
}
Output: 12
If an inner class is intended to be operated only by methods within the outer class, it can be declared as private.
In the code above, we must create an object of In class inside the Out class for operation, and we cannot use Out.In in = new Out().new In()
to create an object of the inner class.
That is, the inner class can only be controlled by the outer class.
Like, my heart can only be controlled by my body; others cannot directly access it.
Example 5: Method Inner Class
class Out {
private int age = 12;
public void Print(final int x) {
class In {
public void inPrint() {
System.out.println(x);
System.out.println(age);
}
}
new In().inPrint();
}
}
public class Demo {
public static void main(String[] args) {
Out out = new Out();
out.Print(3);
}
}
Output:
3
12
In the code above, we moved the inner class to the method of the outer class and then created an object of the inner class within the outer class's method to call the inner class's method.
If we need to pass parameters to the method of the outer class, the formal parameters of the outer class's method must be defined as final.
The use of final here has no special meaning; it's just a form of expression.