内部类就是定义在一个类内部的类。定义在类内部的类有两种情况:一种是被static关键字修饰的, 叫做静态内部类, 另一种是不被static关键字修饰的, 就是普通内部类。 在下文中所提到的内部类都是指这种不被static关键字修饰的普通内部类。 静态内部类虽然也定义在外部类的里面, 但是它只是在形式上(写法上)和外部类有关系, 其实在逻辑上和外部类并没有直接的关系。而一般的内部类,不仅在形式上和外部类有关系(写在外部类的里面), 在逻辑上也和外部类有联系。 这种逻辑上的关系可以总结为以下两点:
1 内部类对象的创建依赖于外部类对象;
2 内部类对象持有指向外部类对象的引用。
上边的第二条可以解释为什么在内部类中可以访问外部类的成员。就是因为内部类对象持有外部类对象的引用。但是我们不禁要问, 为什么会持有这个引用? 接着向下看, 答案在后面。
1
2
3
4
5
6
7
8
9
|
public
class
Outer {
int
outerField =
0
;
class
Inner{
void
InnerMethod(){
int
i = outerField;
}
}
}
|
1
|
javap -classpath . -v Outer$Inner
|
1
|
javap -classpath . -v com.baidu.Outer$Inner
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
{
final
Outer
this
$
0
;
flags: ACC_FINAL, ACC_SYNTHETIC
Outer$Inner(Outer);
flags:
Code:
stack=
2
, locals=
2
, args_size=
2
0
: aload_0
1
: aload_1
2
: putfield #
10
// Field this$0:LOuter;
5
: aload_0
6
: invokespecial #
12
// Method java/lang/Object."<init>":()V
9
:
return
LineNumberTable:
line
5
:
0
LocalVariableTable:
Start Length Slot Name Signature
0
10
0
this
LOuter$Inner;
void
InnerMethod();
flags:
Code:
stack=
1
, locals=
2
, args_size=
1
0
: aload_0
1
: getfield #
10
// Field this$0:LOuter;
4
: getfield #
20
// Field Outer.outerField:I
7
: istore_1
8
:
return
LineNumberTable:
line
7
:
0
line
8
:
8
LocalVariableTable:
Start Length Slot Name Signature
0
9
0
this
LOuter$Inner;
8
1
1
i I
}</init>
|
1
|
final
Outer
this
$
0
;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
Outer$Inner(Outer);
flags:
Code:
stack=
2
, locals=
2
, args_size=
2
0
: aload_0
1
: aload_1
2
: putfield #
10
// Field this$0:LOuter;
5
: aload_0
6
: invokespecial #
12
// Method java/lang/Object."<init>":()V
9
:
return
LineNumberTable:
line
5
:
0
LocalVariableTable:
Start Length Slot Name Signature
0
10
0
this
LOuter$Inner;</init>
|
1
2
3
4
5
6
7
8
|
class
Outer$Inner{
final
Outer
this
$
0
;
public
Outer$Inner(Outer outer){
this
.
this
$
0
= outer;
super
();
}
}
|