Transferred from: http://android.blog.51cto.com/268543/384809
There are two types of internal classes: (1)defining a class within a class(Private inner class, Static inner Class) (2)defining a class in a method(Local inner class, anonymous inner Class)
1. Private inner class--internal class defined between methods, non-staticLet's take a look at the two characteristics of the inner class in the class: (1) You can create an inner class object within the scope of the outer class.even if the inner class is private(Private inner Class). ThatThe inner class is visible to the outer class enclosing it。 For example (in fact, the inner class can be set to public, but generally I'm set as member variable to private)
Code Listing 1: Inner classes visible class outer{ //Create Private Inner class object public Inner in=new Inner (); Private inner classes Private class inner{... }}
(2)all domains whose external classes can be accessed within the inner class, even if the private domain。 That is, the outer class is visible to the inner class. For example
Code Listing 2: External classes visible to inner classes//(inner classes can access all member variables and methods of the outer Class) class outer{ //External class private data field- data=0; Internal class inner{ void print () { //internal class access to external private data domain System.out.println (data); }
The question is: How does the above two features work? What happened to internal "inside" of the class? In fact, the inner class is the Java compiler. The virtual machine does not know what the internal classes are different from the regular classes. How does the compiler hide the virtual machine? After compiling the inner class, it is found that there are two class files: Outer.class and Outer$inner.class. This means that the inner class Inner is still compiled into a separate class (Outer$inner.class) rather than a domain of the Outer class. When a virtual machine is running, inner is treated as a regular class. But the question comes, that is, two general classes, why they can access each other in private domain that (the first mentioned two internal class characteristics)? This will ask the compiler exactly what the two classes are compiled into. We use the reflect reflection mechanism to explore the post-compilation situation of the inner class (the code for probing the internal mechanism of the class is provided in the attachment below Reflect.java). (1), after compiling code 1 generates the Outer$inner.class file, use Reflectutil.reflect ("Outer$inner") to reflect the inner class Inner. The results of the operation found three hidden components:
Anti-compile code class outer$inner{ Outer$inner (outer,outer$inner); Package visible constructor private Outer$inner (Outer); The private constructor sets the this$0 domain final Outer this$0; External class instance domain this$0}
Well, now we can explain the first inner class feature above:
Why can an external class create an object of an inner class? And the inner class can be easily referenced to the external class object?The compiler first compiles the outer and inner classes and puts them in the same package. Attach a package visible constructor to the inner class. In this way, the virtual machine runs the outer class Inner in=new Inner (); The package visible construct is actually called: New Outer$inner (This,null). Therefore, even the private inner class can successfully obtain the construction permission of the private inner class through the implicit package visible constructor. Furthermore, there is a reference this$0 to the outer class Outer in the Outer$inner class, which makes it easy to get the visible members of the Outer class object. But how does the private member of the outer class access it? This will take a look at the secret in the Outer.class file below. (2), compile Code 2 generate the Outer.class file, and then use Reflectutil.reflect ("Outer") to reflect the external partial Outer. The results of the operation found an implied component as follows:
Anti-compile code class Outer { static int access$0 (Outer);
The second feature can now be explained:
why can an inner class reference a private domain of an external class? The key to the reason is that the compiler adds a static method access$0 to the perimeter class. It passes the return value as a parameter to his object domain data. The print statement in this inner class inner: System.out.println (data); When actually running the call is: System.out.println (this$0.access$0 (Outer));
summarize the compiler's hands and feet on the inner classes in the class:
(1) secretly creating the package visible constructor in the inner class, so that the external class gets the Create permission.
(2) A static method that accesses a private variable is secretly created in the outer class, allowing the inner class to gain access.
in this way, the inner class defined in the class can be accessed by the outer class that surrounds it, whether private, public, or static.
2. Static inner class--internal class defined between methods, staticInternal classes also have static differences, which is static inner class, let's look at the code:
Package hr.test; Code Listing 3: Static internal class references to external variables public class outer{ private static int i=0; Create a static inner class object public Inner in=new Inner (); Static inner class private static class inner{public void print () { System.out.println (i); If I is not a static variable, it will not compile } }
The biggest difference between a static inner class and a private inner class is that non-static members of its enclosing class cannot be referenced in a static inner class。 Why is this? Let's take a look at the static inner class Outer$inner what's going on?
Anti-compile code class Outer$inner { private outer$inner ();
Compared to the above private inner class decompile 1 comparison found,a reference to the perimeter class object is missingFinal Outer this$0;That is , the static inner class cannot get a reference to its perimeter class object, so it is natural that the non-static members of the perimeter class cannot be accessed.。
Therefore, a static inner class can only access static members of its enclosing class, except in addition to non-static inner classes.
3. Local inner class--inner class defined in methodThe inner class of the method also has two features (1)the inner class in the method does not have an access modifier, that is, the inner class of the method is not visible to anything other than the method that surrounds it。 (2)method Inner class can only access local variables in the method, so also called local inner class. andand these local variables must be final modified constants.。 For example
Class outter{public void Outmethod () { final int beep=0; Class inner{ //Use beep } Inner in=new Inner ();
Why is that? (1) We first reflect on the Outter class, and there is no hidden way to return the private domain in the outter. (2) The reflection of the inner class is found,inside the inner class, there is a backup hidden field for the beep variable: final int val$i;We can explain this backup constant field in the inner class, firstafter the JVM has run to the point where the inner object needs to be created, the Outter class has all finished running, which is a garbage collection mechanism that is likely to release the local variable beep. So where does the inner class go to find beep variables?
The compiler came out and helped us solve the problem, and he created a beep backup in the inner class ., that is, even if the ouuter in the beep is recycled, there is a backup in inner, nature will not be afraid to find.But here comes the question again.。 If the beep in outter is constantly changing that. Wouldn't it be that the beep variable of the backup changes all the while.
in order to keep local variables consistent with the backup domain in the local inner class . The compiler had to stipulate that these local domains must be constants, once the assignment can no longer change. So why the domain where the local inner class applies the external method must be the reason for the constant field.Summary of characteristics of inner class(1) non-static inner classes defined between methods:the perimeter class and the inner class can access their private members to each other. static member variables cannot be defined in an inner class. (2) static internal classes defined between methods:only static members of external classes can be accessed. (3) The local inner class defined in the method:the inner class does not have any access control permissionsThe perimeter class cannot see the local inner class in the method, but the local inner class can access any member of the perimeter class. The local inner class can be accessed in the method body, but the access statement must be after the local inner class is defined. a local inner class can only access constants in the method body, that is, members that are decorated with a final decoration. (4) Anonymous inner class defined in the method:instead of a constructor, the constructor parameter is passed to the superclass constructor.
"The doubt" to appreciate the "inside" of the Java inner class