In depth analysis based on the role of Java inner classes

  • 2020-04-01 01:50:28
  • OfStack

While many people may not be familiar with Java Inner classes, a similar concept exists in C++, Nested classes, and the differences and connections between the two will be contrasted later. Inner classes on the surface, is in the class also defines a class (see below, the inner class can be defined in many places), but in fact is not so simple, at first glance the inner class seems to be some redundant, it's useful for beginners may not be so significant, but with an in-depth understanding of it, you will find the Java designers, class is well-meaning. Learning to use inner classes is part of mastering advanced Java programming, which allows you to more elegantly structure your programs. Here is the introduction from the following aspects:
First meeting

public interface Contents {
 int value();
}
public interface Destination {
 String readLabel();
}
public class Goods {
 private class Content implements Contents {
  private int i = 11;
  public int value() {
   return i;
  }
 }
 protected class GDestination implements Destination {
  private String label;
  private GDestination(String whereTo) {
   label = whereTo;
  }
  public String readLabel() {
   return label;
  }
 }
 public Destination dest(String s) {
  return new GDestination(s);
 }
 public Contents cont() {
  return new Content();
 }
}
class TestGoods {
 public static void main(String[] args) {
  Goods p = new Goods();
  Contents c = p.cont();
  Destination d = p.dest("Beijing");
 }
}

In this example, the classes Content and GDestination are defined inside the class Goods and have protected and private modifiers to control the access level, respectively. Content represents the Content of the Goods, while GDestination represents the destination of the Goods. They implement two interfaces, Content and Destination, respectively. In the main method that follows, you just use Contents c and Destination d, and you don't even see the names of the two inner classes! In this way, the first benefit of inner classes is to hide operations that you don't want others to know about, namely encapsulation.
At the same time, we discovered the first way to get an inner class object outside the scope of an outer class, which is to create and return it with the methods of its outer class. This is what the cont() and dest() methods in the above example do. Is there any other way?
Of course. The syntax is as follows:
OuterObject = new outerClass (Constructor Parameters);
OuterClass. InnerClass innerObject = outerObject. New innerClass (Constructor Parameters).
Note that when creating a non-static inner class object, be sure to create the corresponding outer class object first. As to why, which brings us to our next topic: non-static inner class objects have references to their outer class objects, To modify the example a little bit:

public class Goods {
 private int valueRate = 2;
 private class Content implements Contents {
  private int i = 11 * valueRate;
  public int value() {
   return i;
  }
 }
 protected class GDestination implements Destination {
  private String label;
  private GDestination(String whereTo) {
   label = whereTo;
  }
  public String readLabel() {
   return label;
  }
 }
 public Destination dest(String s) {
  return new GDestination(s);
 }
 public Contents cont() {
  return new Content();
 }
}

Here we add a private member variable valueRate to the Goods class, meaning the value coefficient of the Goods, which we multiply by the value() method of the inner Content class. We found that value() can access valueRate, which is the second benefit of an inner class. An inner class object can access the contents of the outer class object that created it, even private variables! This is a very useful feature that provides us with more ideas and shortcuts when designing. To do this, an inner class object must have a reference to an outer class object. When the Java compiler creates an inner class object, it implicitly passes in references to its outer class object and keeps them there. This allows an inner class object to always have access to its outer class object, which is why an outer class object must be created before an inner class object is created outside the scope of the outer class.
One might ask, what if a member variable in an inner class has the same name as a member variable in an outer class, that is, the member variable with the same name in the outer class is masked? No problem. In Java, external class references are expressed in the following format:
OuterClass. This
With it, we're not afraid of this kind of shielding.

Static inner class

Just like regular classes, inner classes can be static. But the difference with non-static inner classes is that they have no references to the outside. This is actually very similar to nested classes in C++, and the biggest difference between Java inner classes and C++ nested classes is whether or not there is a reference to the outside, from a design point of view and in some of its details.
In addition, you cannot have static data, static methods, or another static inner class in any non-static inner class (nested inner classes can have more than one layer). But you can have it all in a static inner class. That's the second difference.

Local inner class

Yes, Java inner classes can also be local, defined within a method or even a block of code.

public class Goods1 {
 public Destination dest(String s) {
  class GDestination implements Destination {
   private String label;
   private GDestination(String whereTo) {
    label = whereTo;
   }
   public String readLabel() {
    return label;
   }
  }
  return new GDestination(s);
 }
 public static void main(String[] args) {
  Goods1 g = new Goods1();
  Destination d = g.dest("Beijing");
 }
}

Here's an example. In the method dest we define an inner class that returns the object of the inner class. We can do this if we only need to create one object of an inner class and create it externally. Of course, inner classes defined in methods can diversify the design, and that's not all.
Here's an even stranger example:

public class Goods2 {
 private void internalTracking(boolean b) {
  if (b) {
   class TrackingSlip {
    private String id;
    TrackingSlip(String s) {
     id = s;
    }
    String getSlip() {
     return id;
    }
   }
   TrackingSlip ts = new TrackingSlip("slip");
   String s = ts.getSlip();
  }
 }
 public void track() {
  internalTracking(true);
 }
 public static void main(String[] args) {
  Goods2 g = new Goods2();
  g.track();
 }
}

You cannot create the object of this inner class outside of if because it is out of scope. However, at compile time, the inner class TrackingSlip is compiled at the same time as any other class, except that it is not valid beyond its scope because it is in its own scope. Otherwise, it is no different from any other inner class.

Anonymous inner class

Java's syntax for anonymous inner classes is a bit odd, but like anonymous arrays, using inner classes makes your code look clean when you only need to create an object of a class and you don't need its name. Its grammar rules are as follows:
New interfacename () {... }; Or new superclassname () {... };
Here are some more examples:

public class Goods3 {
 public Contents cont() {
  return new Contents() {
   private int i = 11;
   public int value() {
    return i;
   }
  };
 }
}

Here the method cont() USES an anonymous inner class to directly return an object that implements the Contents of the interface.
Anonymous inner classes are heavily used in anonymous adapters for event handling in Java. For example, when you want to close a window, add this code:

frame.addWindowListener(new WindowAdapter(){
 public void windowClosing(WindowEvent e){
    System.exit(0);
 }
}); 

It is important to note that the anonymous inner class has no constructor because it has no name (but if the anonymous inner class inherits a parent class that contains only a constructor with parameters, it must be created with those parameters and called with the corresponding super keyword during implementation). If you want to initialize its member variables, there are several ways:
If you are in an anonymous inner class of a method, you can use this method to pass in the parameters you want, but remember that these parameters must be declared final.

Transform the anonymous inner class into a local inner class with a name so that it can have a constructor.
Use the initialization block in this anonymous inner class.
Why do we need inner classes?

What are the benefits of Java inner classes? Why do we need inner classes?
Let's start with a simple example. If you want to implement an interface, but a method in the interface has the same name and parameters as a method in the class you're imagining, what should you do? At this point, you can build an inner class to implement the interface. Because all of the content of the inner class is accessible to the outer class, doing so accomplishes all of the functionality you need to implement the interface directly.

But you may want to question, change the method of not line?
Indeed, this is not a compelling reason to design inner classes.
The real reason is that the inner classes and interfaces in Java add up to solve a problem that C++ programmers often complain about in Java. In fact, C++ 's multi-inheritance design is very complex, and Java can achieve the effects of multi-inheritance very well through inner classes and interfaces.

Related articles: