There are many types of inner classes in Java, and the syntax is complex and the usage is not the same. In summary, it can be classified into the following five inner classes.

  1. The inner class
  2. Nested inner classes
  3. Local inner class
  4. Interface inner class
  5. Anonymous inner class

This article only gives a brief introduction to common and anonymous inner classes, which are often used in actual project development. If you are interested in the other three, please find out by yourself through Google or books.

The inner class

Let’s start by looking at the syntax of inner classes with a simple little example.

import java.util.HashMap;

public class Parcell {

    private HashMap<String, String> testMap = new HashMap<String, String>();

    class Contents {
        // Returns a reference to an external class.
        public Parcell ParcellRef = Parcell.this;
    }

    class Destination {
        public void putSomethingInMap(a) {
            testMap.put("hello"."world");
            System.out.println(testMap.get("hello")); }}public Destination to(a) {
        return new Destination();
    }

    public Contents contents(a) {
        return new Contents();
    }

    public void ship(String dest) {
        Contents c = new Contents();
        Destination d = new Destination();
    }

    public static void main(String[] args) {
        Parcell p = newParcell(); Parcell.Contents c = p.contents(); Parcell.Destination d = p.to(); d.putSomethingInMap(); Parcell.Contents c1 = p.new Contents(); }}Copy the code

The syntax and syntax of inner classes are familiar. Here I again take the liberty of generalizing for everyone

  1. The normal inner class holds a reference to the outer class. To create a normal inner class, be sure to create an outer class first.
  2. Like the heart of the human body, a normal inner class can access any member variable of the outer class at will.
  3. An inner class can return a reference to an instance of the outer class by saying “outer class name.this”. Such as the Parcell. This
  4. If you want to create an inner class object in the static method of an outer class, you need to create an inner class object by saying “outer class name.new XXX()”.
  5. A normal inner class cannot have static member variables. Static inner classes can have static member variables. You can also have non-static member variables. But a static inner class cannot access a non-static member variable of an outer class. A normal inner class can access static member variables of an outer class.

Why do we create an object using p.new XXX() instead of the inner class name? If you have such a question please look at the first, you can figure it out.

That’s pretty much the syntax for ordinary inner classes. So, back to the subject.

What are inner classes really for? How should we use inner classes in real projects? The usefulness, or usage, of inner classes boils down to one thing: “Inner classes are primarily designed to address the concept of multiple inheritance that is’ missing ‘in Java.”

What? Doesn’t Java rely on interfaces to implement multiple inheritance? In my opinion, this statement is both true and false. Let’s look at an example.

You’re working on a starship project code-named X.

NASA hopes the integrated robot on board will do two things. One is to serve as a guide for people to look up information. Second, as a repair robot, to complete some simple spacecraft daily maintenance work.

As a software engineer, you are required to write a piece of code that implements both functions.

The good news is that the guiding and ship repair functions have already been done by your colleagues! Great, I just need to call the interface they give us and we’re done!

The bad news is that the interface between the wizard function and the ship repair function written by my colleagues is called Work!

It’s nerve-racking. What should I do?

public class Guider {

    public void work(String name) {
        System.out.println("Welcome." + name + "Please check the ship information."); }} -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --public class Repairer {
    
    public void work (String name) {
        System.out.println("Hello" + name + ", to prepare the ship for maintenance."); }} -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --public class SpacecraftRobot extends Guider {
    
    
    public void doGuidWork(String name) { 
        // Call guider's work method
        work(name);
    }
    
    public void doRepairWork(String name) {
        // Return the inner class reference, calling the work method of the inner class instance.
        new repairerRobot().doRepairWork(name);
    }
    
    public class repairerRobot extends Repairer {
        
        public void doRepairWork(String name) { work(name); }}}Copy the code

That’s great. We implement this functionality by using inner classes and “multiple inheritance.” Now the integrated robot is working properly!

For the user, just walk up to the robot and tell the robot whether you want doGuidWork or doRepairWork, and it can do the job for you. The code of the inner class is completely hidden from the user and the outside world, and the only information available to the user is the two methods.

Anonymous inner class

After a successful trial of the integrated robot prototype, the new job comes!

We need to mass-produce the prototype. To meet the needs of each starship.

Now we’re going to write a factory that produces an integrated robot. Every time we visit the factory, we can extract a brand new integrated robot from the factory. You are smart enough to think of factory design patterns to solve this problem! But with the inner class, our factory is a little bit different

// Robot factory interface. Provide robots externally through the getSpaceCraftRobot method
public interface SpaceCraftRobotFactory {
    SpacecraftRobot getSpaceCraftRobot(a); } -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --public class ProduceSpaceCraftRobot {
    // No longer need to display the object to create the factory class!
    private ProduceSpaceCraftRobot(a) {}// Create factory objects via anonymous inner classes! Encapsulate the factory in-house. To the outside world.
    public static SpaceCraftRobotFactory produceRobot = new SpaceCraftRobotFactory () {
        public SpacecraftRobot getSpaceCraftRobot(a) {
            return newSpacecraftRobot(); }}; } -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --/ / customer
public class Consumer {

    public static void main(String[] args) {
        // The client is coming to pick up the robot.
        SpacecraftRobot x1 = ProduceSpaceCraftRobot.produceRobot.getSpaceCraftRobot();
        x1.doGuidWork("lch");
        x1.doRepairWork("lch"); }}Copy the code

By creating anonymous inner classes, we’ve made traditional factory design patterns much more elegant! No more ugly, redundant code like new xxxFactory() written externally.

The factory is now hidden by anonymous inner classes. All the customers need to care about is getting the robot they want. No, you don’t need to know the name of the factory, you don’t need to know what the factory does.

Good for you. You did what NASA asked you to do. Congratulations. You’re a hero on this planet.

Closures in Java, the relationship between closures and inner classes

As a programmer, you’ve probably heard of closures and callbacks, even if you’ve never used them. It can be difficult to explain closures and callbacks from the perspective of Java, and particularly J2EE. So let’s start with Python to understand what closures and callbacks really are.

Python is an excellent interpreted language. You should master him.

Let’s take a look at what a standard callback looks like in Python.

Define a function called base_sum that returns sum
def base_sum(a,b):
    Define a sum() function in base_sum to calculate the concatenation of parameters in base_sum(a,b)
    def sum(a):
        Return the value of a+b
        return a + b
    # return the sum function defined
    return sum
The base_sum function returns sum(), which returns a pointer to the function
return_method = base_sum(1.2)
Print out the returned function object
print(return_method)
Return the join of a and b via the pointer callback object
print(return_method())

----------
<function base_sum.<locals>.sum at 0x1018f3c80>
3
Copy the code

For Java programmers, defining another function in one function can be a bit of a brainer. You can try to understand it this way: “The first thing you need to understand is that functions also take up memory space, so functions also have addresses in memory. In C, the name of a function represents the address of the function. If you’ve had any programming experience with C, you know that returning a pointer to a function is an easy thing to do. So, you can try to interpret this python code as: the base_sum() function defines a pointer to the sum() function as the return value of base_sum().”

Ok, now let’s “define closures” based on the above example. Closure: Calls an external function and returns a program structure that holds an internal function object with a reference to the external function variables and arguments.

Unfortunately, Java does not provide Pointers to what we display for manipulation, nor does it provide syntax similar to python’s, javascrpit’s, function definitions. So how do we implement closures? Might as well answer this question through the synthetic robot. This time, let’s modify the synthetic robot code slightly as follows:

public class SpacecraftRobot extends Guider {
    // A member variable of the external class
    private String name;
    
    public SpacecraftRobot(String name) {
        this.name = name;
    }
    
    public class repairerRobot extends Repairer {
        
        public void doRepairWork(a) {
            // The inner class holds a reference to the outer class and accesses the member variable name of the outer class.work(name); }}public void doGuidWork(a) { 
        // Call guider's work method
        work(name);
    }
    
    public void doRepairWork(a) {
        // Returns an object that holds a reference to the inner class of the external class variable, and then calls this object to implement the concrete business logic.
        newrepairerRobot().doRepairWork(); }}Copy the code

By making good use of Java inner classes, we “simulate” the structure of a closure. The program returns an inner class object that holds a reference to the variable of the outer class object by calling the outer class object. When we call a method of an inner class object again, we implement concrete business logic.

conclusion

  1. Inner classes are often used to solve the problem of “multiple inheritance.”
  2. When you want to hide the implementation of a class, reducing the number of.Java files in your project, or if the class does not want to be extended, you can create an object of a class by anonymous inner classes.
  3. While Java cannot support closures directly at the syntactic level, it is possible to simulate the program structure of a closure through inner classes.