Four Internal Classes in Java

Internal classes refer to redefining a class within an external class. The class name does not need to be the same as the folder.
(Note that the external class here is the most common common common class, which is called "internal class" only to correspond to the internal class.)
Internal classes are a compile-time concept, and once compiled successfully, they become two completely different classes. For an external class named outer and its internally defined inner class named inner. After compilation, there are two classes: outer.class and outer$inner.class. So the member variables / method names of internal classes can be the same as those of external classes.

I. Internal Classes of Members

Membership inner class, as a member of external class, can directly use all members and methods of external class, even private. At the same time, external classes need to access all member variables/methods of internal classes through objects of internal classes.
It's important to note that member inner classes cannot contain static variables and methods. Because internal classes of members need to create external classes before they can create their own.
External class objects are represented by outer.this when internal class of member refers to external class objects.
To create an internal class object, you can use outer. inner obj = outerobj. new inner ();

public class Outer { 
    public class Inner { 
        public void print(String str) { 
            System.out.println(str); 
        } 
    } 
 
    public Inner getInner() { 
        return new Inner(); 
    } 
  
    public static void main(String[] args) { 
        Outer outer = new Outer(); 
        Outer.Inner inner = outer.new Inner(); 
        inner.print("Outer.new"); 
 
        inner = outer.getInner(); 
        inner.print("Outer.get"); 
    } 
}

Operation results:
Outer.new
Outer.get

II. Local Internal Classes

Local inner classes are classes defined in a method or scope. The difference between them and member inner classes is that access to local inner classes is limited to method or scope.

class People{
    public People() {
         
    }
}
 
class Man{
    public Man(){
         
    }
     
    public People getWoman(){
        class Woman extends People{   //Local inner class
            int age =0;
        }
        return new Woman();
    }
}

Note that local inner classes, like a local variable in a method, cannot have public, protected, private, and static modifiers.

III. Static Internal Classes

Static inner classes are also classes defined in another class, except that there is an additional keyword static in front of the class. Static inner classes do not need to depend on external classes, which is similar to static member properties of classes, and it can not use non-static member variables or methods of external classes. This is well understood, because in the absence of objects of external classes, objects of static inner classes can be created. If non-static members of external classes are allowed to be accessed, contradictions will arise because Non-static members of external classes must be attached to specific objects.

class Outter {
    public Outter() {
         System.out.println("Outter constructor.");
    }
     
    static class Inner {
        public Inner() {
            System.out.println("Inner constructor.");             
        }
    }
}

public class Test {
    public static void main(String[] args)  {
        Outter.Inner inner = new Outter.Inner();
    }
}

Operation results:
Inner constructor.

IV. Anonymous Internal Classes

(1) Definition

As the name implies, anonymous inner classes are inner classes without names.
Because there is no name, anonymous inner classes can only be used once, which is usually used to simplify code writing.
There is a prerequisite for using anonymous inner classes: you must inherit a parent class or implement an interface.

(2) Examples

Example 1: Implementing abstract methods without anonymous inner classes

abstract class Person {
    public abstract void eat();
}
 
class Child extends Person {
    public void eat() {
        System.out.println("eat something");
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Child();
        p.eat();
    }
}

Running result: eat something

As you can see, we inherited the Person class with Child, and then implemented an instance of Child, transforming it upwards into a reference to the Person class.
However, if the Child class here is only used once, would it not be too cumbersome to write it as a separate class?
At this point, you can consider introducing anonymous inner classes.

Example 2: Basic implementation of anonymous inner classes

abstract class Person {
    public abstract void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

Running result: eat something

As you can see, we directly implemented the method in the abstract class Person in braces. In this way, the writing of a class can be omitted.
Anonymous internal classes can also be used on interfaces.

Example 3: Using anonymous inner classes on interfaces

interface Person {
    public void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

Running result: eat something

The most common use of anonymous internal classes is in multithreaded implementations, because to achieve multithreading, you must inherit the Thread class or implement the Runnable interface.

Example 4: Anonymous inner class implementation of Thread class

public class Demo {
    public static void main(String[] args) {
        Thread t = new Thread() {
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
        t.start();
    }
}

Running results: 1 234 5

Example 5: Implementation of anonymous inner class of Runnable interface

public class Demo {
    public static void main(String[] args) {
        Runnable r = new Runnable() {
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
        Thread t = new Thread(r);
        t.start();
    }
}

Running results: 1 234 5

(3) Role

1) A class is used to inherit other classes or implement interfaces. It does not need additional methods, but implements or overrides inherited methods.
2) In order to obtain an object instance, it is not necessary to know its actual type.
3) Class names are meaningless, that is, they do not need to be used.

Added by nocniagenti on Sun, 02 Jun 2019 23:28:18 +0300