静态内部类
public class Anonymous {
static String a = "sss";
void fun(){
new Inner().fun();
}
static class Inner {
void fun () {
System.out.println(a);
}
}
}
使用javac Anonymous可以得到Anonymous.class和Anonymous$Inner.class两个字class文件
在IDE中反编译class文件:
Anonymous.class:
public class Anonymous {
static String a = "sss";
public Anonymous() {
}
void fun() {
(new Anonymous.Inner()).fun();
}
static class Inner {
Inner() {
}
void fun() {
System.out.println(Anonymous.a);
}
}
}
Anonymous$Inner.class:
class Anonymous$Inner {
Anonymous$Inner() {
}
void fun() {
System.out.println(Anonymous.a);
}
}
字节码javap -c Anonymous :
public class main.com.example.train.Anonymous {
static java.lang.String a;
public main.com.example.train.Anonymous();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
void fun();
Code:
0: new #2 // class main/com/example/train/Anonymous$Inner
3: dup
4: invokespecial #3 // Method main/com/example/train/Anonymous$Inner."<init>":()V
7: invokevirtual #4 // Method main/com/example/train/Anonymous$Inner.fun:()V
10: return
static {};
Code:
0: ldc #5 // String sss
2: putstatic #6 // Field a:Ljava/lang/String;
5: return
}
字节码javap -c Anonymous$Inner :
class main.com.example.train.Anonymous$Inner {
main.com.example.train.Anonymous$Inner();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
void fun();
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: getstatic #3 // Field main/com/example/train/Anonymous.a:Ljava/lang/String;
6: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
9: return
}
结论:
- 静态内部类会编译成一个新类
- 静态内部类直接访问外部类的静态变量(getstatic指令)
成员内部类
public class Anonymous {
private String a ;
void fun(){
new Inner().fun();
}
class Inner {
void fun () {
System.out.println(a);
}
}
}
Anonymous$Inner.class:
class Anonymous$Inner {
Anonymous$Inner(Anonymous var1) {
this.this$0 = var1;
}
void fun() {
System.out.println(this.this$0.a);
}
}
字节码:
public class main.com.example.train.Anonymous {
public main.com.example.train.Anonymous();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
void fun();
Code:
0: new #2 // class main/com/example/train/Anonymous$Inner
3: dup
4: aload_0
5: invokespecial #3 // Method main/com/example/train/Anonymous$Inner."<init>":(Lmain/com/example/train/Anonymous;)V
8: invokevirtual #4 // Method main/com/example/train/Anonymous$Inner.fun:()V
11: return
}
class Anonymous$Inner {
Anonymous$Inner(Anonymous var1) {
this.this$0 = var1;
}
void fun() {
System.out.println(this.this$0.a);
}
}
结论:
-
局部内部类也是编译成一个新类
-
局部内部类的构造方法的参数包含外部类
-
new一个局部内部类时会传入外部类对象的引用
(aload_0 is supposed to push 'this' on to the stack)
-
内部类访问外部类的变量是通过传入的外部类对象进行访问
局部类
方法中的类即为局部类
public class Anonymous {
private String a;
void fun() {
class Inner {
void fun() {
System.out.println(a);
}
}
new Inner().fun();
}
}
Anonymous$1Inner
class Anonymous$1Inner {
Anonymous$1Inner(Anonymous var1) {
this.this$0 = var1;
}
void fun() {
System.out.println(this.this$0.a);
}
}
字节码:
public class main.com.example.train.Anonymous {
public main.com.example.train.Anonymous();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
void fun();
Code:
0: new #2 // class main/com/example/train/Anonymous$1Inner
3: dup
4: aload_0
5: invokespecial #3 // Method main/com/example/train/Anonymous$1Inner."<init>":(Lmain/com/example/train/Anonymous;)V
8: invokevirtual #4 // Method main/com/example/train/Anonymous$1Inner.fun:()V
11: return
}
和成员内部类相似。
匿名内部类
没有名字的内部类。。
public class Anonymous {
private String a;
void fun() {
Inner inner = new Inner() {
@Override
public void fun() {
}
};
inner.fun();
}
interface Inner {
void fun();
}
}
Anonymous$1.class :
class Anonymous$1 implements Inner {
Anonymous$1(Anonymous var1) {
this.this$0 = var1;
}
public void fun() {
}
}
字节码:
public class main.com.example.train.Anonymous {
public main.com.example.train.Anonymous();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
void fun();
Code:
0: new #2 // class main/com/example/train/Anonymous$1
3: dup
4: aload_0
5: invokespecial #3 // Method main/com/example/train/Anonymous$1."<init>":(Lmain/com/example/train/Anonymous;)V
8: astore_1
9: aload_1
10: invokeinterface #4, 1 // InterfaceMethod main/com/example/train/Anonymous$Inner.fun:()V
15: return
}
与局部内部类相似,匿名内部类的构造方法需要外部类对象作为参数,然后,匿名内部类通过这个对象访问外部类的变量和方法。