java Enhancement (7) - - Details of Internal Classes

Keywords: Java Programming

  

You can place the definition of one class inside the definition of another class, which is the internal class.

Internal classes are a very useful but difficult feature to understand (I haven't used them very much so far, and I know only a little about them).

First meeting

Internal classes are very easy to understand from the outside, just to define a class inside a class.

  1. public class OuterClass {  
  2.     private String name ;  
  3.     private int age;  
  4.   
  5.     public String getName() {  
  6.         return name;  
  7.     }  
  8.   
  9.     public void setName(String name) {  
  10.         this.name = name;  
  11.     }  
  12.   
  13.     public int getAge() {  
  14.         return age;  
  15.     }  
  16.   
  17.     public void setAge(int age) {  
  18.         this.age = age;  
  19.     }  
  20.       
  21.     class InnerClass{  
  22.         public InnerClass(){  
  23.             name = "chenssy";  
  24.             age = 23;  
  25.         }  
  26.     }  
  27. }  

InnerClass is the inner class here. For beginners, the inner class is really not used much. The same is not used by the beginner (it seems only used in swing registration events), but as the programming ability improves, we will understand its charm. It can use more elegant design of our program structure. . Between using internal classes, we need to understand why we use internal classes and what benefits internal classes can bring us.


1. Why use internal classes

Why use internal classes? In Think in Java > There is a saying that the most attractive reason for using inner classes is that each inner class can inherit an implementation independently, so whether or not the outer class has inherited an implementation has no effect on the inner class.

In our programming, there are some problems that are difficult to solve by using interfaces. At this time, we can solve these programming problems by utilizing the ability of internal classes to inherit multiple concrete or abstract classes. It can be said that interfaces solve only part of the problem, while internal classes make the solution of multiple inheritance more complete.

  1. public interface Father {  
  2.   
  3. }  
  4.   
  5. public interface Mother {  
  6.   
  7. }  
  8.   
  9. public class Son implements Father, Mother {  
  10.   
  11. }  
  12.   
  13. public class Daughter implements Father{  
  14.   
  15.     class Mother_ implements Mother{  
  16.           
  17.     }  
  18. }  

In fact, we can't see the advantages of using internal classes for this example, but what if Father and Mother are not interfaces, but abstract classes or concrete classes? At this point, we can only use internal classes to achieve multiple inheritance.

In fact, the greatest advantage of using internal classes is that it can solve the problem of multiple inheritance very well, but if we do not need to solve the problem of multiple inheritance, then we can naturally use other coding methods, but using internal classes can also bring us the following features (from Think in java):

Internal classes can use multiple instances, each of which has its own state information and is independent of the information of other peripheral objects.

2. In a single peripheral class, multiple internal classes can implement the same interface in different ways, or inherit the same class.

3. The creation of internal class objects does not depend on the creation of peripheral class objects.

4. There is no confusing "is-a" relationship between the inner class and it is an independent entity.

5. Internal classes provide better encapsulation. Except for the peripheral classes, no other classes are accessible.


Internal Class Foundation

This section focuses on how internal classes use the attributes and methods of external classes, as well as the use of. this and. new.

When we create an inner class, it has an invisible connection with the outer class, depending on which it can access the elements of the outer class without restriction.

  1. public class OuterClass {  
  2.     private String name ;  
  3.     private int age;  
  4.   
  5.     /**Omitting getter and setter methods**/  
  6.       
  7.     public class InnerClass{  
  8.         public InnerClass(){  
  9.             name = "chenssy";  
  10.             age = 23;  
  11.         }  
  12.           
  13.         public void display(){  
  14.             System.out.println("name: " + getName() +"   ;age: " + getAge());  
  15.         }  
  16.     }  
  17.       
  18.     public static void main(String[] args) {  
  19.         OuterClass outerClass = new OuterClass();  
  20.         OuterClass.InnerClass innerClass = outerClass.new InnerClass();  
  21.         innerClass.display();  
  22.     }  
  23. }  
  24. --------------  
  25. Output:   
  26. name: chenssy   ;age: 23  

In this application, we can see that InnerClass can seamlessly access the attributes of the peripheral class OuterClass, although it is private ly modified. This is because when we create an internal class object of a peripheral class, the internal class object must capture a reference to that peripheral class object, which is used to select the members of the peripheral class whenever we access the members of the peripheral class.

In fact, in this application we also see how to refer to internal classes: referring to internal classes we need to specify the type of the object: OuterClasName.InnerClassName. At the same time, if we need to create an internal class object, we must use the object of the external class to create an internal class through. new: OuterClass.InnerClass innerClass = outerClass.new InnerClass();.

At the same time, if we need to generate a reference to an external class object, we can use OuterClassName.this, so that we can produce a reference to the external class correctly. Of course, this is known at compile time, and there is no runtime cost.

  1. public class OuterClass {  
  2.     public void display(){  
  3.         System.out.println("OuterClass...");  
  4.     }  
  5.       
  6.     public class InnerClass{  
  7.         public OuterClass getOuterClass(){  
  8.             return OuterClass.this;  
  9.         }  
  10.     }  
  11.       
  12.     public static void main(String[] args) {  
  13.         OuterClass outerClass = new OuterClass();  
  14.         OuterClass.InnerClass innerClass = outerClass.new InnerClass();  
  15.         innerClass.getOuterClass().display();  
  16.     }  
  17. }  
  18. -------------  
  19. Output:  
  20. OuterClass...  

At this point, we need to make it clear that internal classes are a compile-time concept, and once compiled successfully, they belong to two completely different classes (of course, they are related to each other). For a peripheral class named OuterClass and an internal class named InnerClass, after successful compilation, two class files will appear: OuterClass.class and OuterClass$InnerClass.class.

Internal classes in Java are mainly divided into member internal classes, local internal classes, anonymous internal classes and static internal classes.


Internal Classes of Members

The member inner class is also the most common inner class. It is a member of the peripheral class, so it can access all the member attributes and methods of the peripheral class without restriction. Although it is private, the member attributes and methods of the peripheral class need to be accessed through the inner class instance to access the member attributes and methods of the inner class.

There are two points to be noted in the inner class of a member: first, there can be no static variables and methods in the inner class of a member; second, the inner class of a member is dependent on the outer class, so the inner class can only be created by creating the outer class first.

  1. public class OuterClass {  
  2.     private String str;  
  3.       
  4.     public void outerDisplay(){  
  5.         System.out.println("outerClass...");  
  6.     }  
  7.       
  8.     public class InnerClass{  
  9.         public void innerDisplay(){  
  10.             //Use periphery attributes  
  11.             str = "chenssy...";  
  12.             System.out.println(str);  
  13.             //Use peripheral and internal methods  
  14.             outerDisplay();  
  15.         }  
  16.     }  
  17.       
  18.     /*It is recommended to use getxx () to obtain member inner classes, especially when the constructor of the inner class has no parameters.*/  
  19.     public InnerClass getInnerClass(){  
  20.         return new InnerClass();  
  21.     }  
  22.       
  23.     public static void main(String[] args) {  
  24.         OuterClass outer = new OuterClass();  
  25.         OuterClass.InnerClass inner = outer.getInnerClass();  
  26.         inner.innerDisplay();  
  27.     }  
  28. }  
  29. --------------------  
  30. chenssy...  
  31. outerClass...  

getxxx() is recommended to obtain member inner classes, especially when the constructor of the inner class has no parameters.


Local internal classes

There is such an internal class, which is nested in methods and functions. The use of this class is mainly to apply and solve more complex problems. We want to create a class to assist our solution. At that time, we don't want this class to be publicly available, so we have local internal classes, which are compiled just like member internal classes. Its scope has changed, it can only be used in this method and attributes, out of which the method and attributes will be invalid.

There are really no good examples for local internal classes, so we quote the classic example in Think in java.

Defined in the method:

  1. public class Parcel5 {  
  2.     public Destionation destionation(String str){  
  3.         class PDestionation implements Destionation{  
  4.             private String label;  
  5.             private PDestionation(String whereTo){  
  6.                 label = whereTo;  
  7.             }  
  8.             public String readLabel(){  
  9.                 return label;  
  10.             }  
  11.         }  
  12.         return new PDestionation(str);  
  13.     }  
  14.       
  15.     public static void main(String[] args) {  
  16.         Parcel5 parcel5 = new Parcel5();  
  17.         Destionation d = parcel5.destionation("chenssy");  
  18.     }  
  19. }  

Define in scope:

  1. public class Parcel6 {  
  2.     private void internalTracking(boolean b){  
  3.         if(b){  
  4.             class TrackingSlip{  
  5.                 private String id;  
  6.                 TrackingSlip(String s) {  
  7.                     id = s;  
  8.                 }  
  9.                 String getSlip(){  
  10.                     return id;  
  11.                 }  
  12.             }  
  13.             TrackingSlip ts = new TrackingSlip("chenssy");  
  14.             String string = ts.getSlip();  
  15.         }  
  16.     }  
  17.       
  18.     public void track(){  
  19.         internalTracking(true);  
  20.     }  
  21.       
  22.     public static void main(String[] args) {  
  23.         Parcel6 parcel6 = new Parcel6();  
  24.         parcel6.track();  
  25.     }  
  26. }  


5. Anonymous Internal Classes

In Swing programming, we often use this way to bind events

  1. button2.addActionListener(    
  2.                 new ActionListener(){    
  3.                     public void actionPerformed(ActionEvent e) {    
  4.                         System.out.println("You pressed button 2");    
  5.                     }    
  6.                 });  

At first glance, we may find it very strange, because this inner class has no name. Look at the following example:

  1. public class OuterClass {  
  2.     public InnerClass getInnerClass(final int num,String str2){  
  3.         return new InnerClass(){  
  4.             int number = num + 3;  
  5.             public int getNumber(){  
  6.                 return number;  
  7.             }  
  8.         };        /* Note: Semi-colons should not be saved.*/  
  9.     }  
  10.       
  11.     public static void main(String[] args) {  
  12.         OuterClass out = new OuterClass();  
  13.         InnerClass inner = out.getInnerClass(2"chenssy");  
  14.         System.out.println(inner.getNumber());  
  15.     }  
  16. }  
  17.   
  18. interface InnerClass {  
  19.     int getNumber();  
  20. }  
  21.   
  22. ----------------  
  23. Output:  
  24. 5  

Here we need to see a few places.

1. Anonymous inner classes have no access modifiers.

2. new anonymous inner class, which is the first class to exist. If we annotate that InnerClass interface, there will be a compilation error.

3. Note the parameters of the getInnerClass() method. The first parameter is modified with final, but the second parameter is not. At the same time, we also find that the second parameter has not been used in the anonymous inner class, so when the parameter of the method needs to be used by the anonymous inner class, the parameter must be final.

4. Anonymous inner classes are not constructed. Because it has no way to construct names.

PS: Because of the limited space, this is the introduction of anonymous inner classes. For more information about anonymous inner classes, I will give a detailed introduction in the next blog (java Enhancement - - - Explaining anonymous inner classes in detail), including why the formal parameters should be defined as final, how to initialize anonymous inner classes, etc. Please look forward to...


Sixth, Static Internal Classes

Static can modify member variables, methods, code blocks, and other internal classes. Static can modify internal classes, which we call static internal classes, but we prefer to call nested internal classes. There is a big difference between static inner classes and non-static inner classes. We know that non-static inner classes implicitly store a reference after compilation. The reference refers to the periphery of creating it, but static inner classes do not. Without this reference, it means:

1. Its creation does not depend on peripheral classes.

2. It cannot use non-static member variables and methods of any peripheral class.

  1. public class OuterClass {  
  2.     private String sex;  
  3.     public static String name = "chenssy";  
  4.       
  5.     /** 
  6.      *Static inner class 
  7.      */  
  8.     static class InnerClass1{  
  9.         /* Static members can exist in static inner classes*/  
  10.         public static String _name1 = "chenssy_static";  
  11.           
  12.         public void display(){  
  13.             /*  
  14.              * Static internal classes can only access static member variables and methods of peripheral classes 
  15.              * Non-static member variables and methods that cannot access peripheral classes 
  16.              */  
  17.             System.out.println("OutClass name :" + name);  
  18.         }  
  19.     }  
  20.       
  21.     /** 
  22.      * Non-static internal classes 
  23.      */  
  24.     class InnerClass2{  
  25.         /* Static members cannot exist in non-static inner classes*/  
  26.         public String _name2 = "chenssy_inner";  
  27.         /* Any member of a peripheral class can be invoked in a non-static inner class, whether static or non-static.*/  
  28.         public void display(){  
  29.             System.out.println("OuterClass name: " + name);  
  30.         }  
  31.     }  
  32.       
  33.     /** 
  34.      * @desc Peripheral Class Method 
  35.      * @author chenssy 
  36.      * @data 2013-10-25 
  37.      * @return void 
  38.      */  
  39.     public void display(){  
  40.         /* Peripheral classes access static inner classes: inner classes.*/  
  41.         System.out.println(InnerClass1._name1);  
  42.         /* Static inner classes can create instances directly without relying on peripheral classes.*/  
  43.         new InnerClass1().display();  
  44.           
  45.         /* Non-static internal creation needs to depend on peripheral classes*/  
  46.         OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();  
  47.         /* Members of azimuth non-static inner classes need to use instances of non-static inner classes*/  
  48.         System.out.println(inner2._name2);  
  49.         inner2.display();  
  50.     }  
  51.       
  52.     public static void main(String[] args) {  
  53.         OuterClass outer = new OuterClass();  
  54.         outer.display();  
  55.     }  
  56. }  
  57. ----------------  
  58. Output:  
  59. chenssy_static  
  60. OutClass name :chenssy  
  61. chenssy_inner  
  62. OuterClass name: chenssy  

The above example fully demonstrates the difference between static internal classes and non-static internal classes.

The introduction of internal classes is almost over here! In fact, I know only the fur for the inner class, approaching a rookie, and my knowledge is limited! I will use these days to study the internal classes!

Posted by phpnoobie on Thu, 20 Jun 2019 15:09:11 -0700