初学者对java匿名内部类构造原理的分析 (散分)

ZangXT 2008-07-28 08:07:11
学Java 虽然时间不算太长,但是对一些原理性的东西很感兴趣。今天分析了一下匿名内部类调用构造方法的原理,希望高手拍砖。
因为匿名内部类没有名字这个特殊性质,所以我们无从给它指定构造方法,构造方法必须和类名同名,类名都没有,构造方法就无从谈起了。但是匿名内部类可以通过直接调用父类的构造方法实现初始化,当然要求父类构造方法对它父类中定义的成员变量进行初始化。这里用一个例子看创建匿名内部类的时候父类的构造方法到底是如何调用的。

public class Main {

public static void main(String[] args) {
InnerTest inner = new InnerTest();
Test t = inner.get(3);
System.out.println(t.getI());
}
}

class Test { //超类
private int i;
public Test(int i) {
this.i = i;
}
public int getI() {
return i;
}
}

class InnerTest { //用于内部类的测试
public Test get(int x) {
return new Test(x) { //创建匿名内部类,调用父类的构造方法
@Override
public int getI() {
return super.getI() * 10;
}
};
}
}

编译得到4个class文件,这里只需要关注InnerTest.class 和 InnerTest$1.class。这里InnerTest$1.class是匿名内部类的class文件,InnerTest.class是InnerTest类的class文件。我们先看InnerTest$1.class的内容:
javap -c InnerTest$1 > InnerTest$1.txt
得到代码如下 :

Compiled from "Main.java"
class InnerTest$1 extends Test{
final InnerTest this$0;

InnerTest$1(InnerTest, int);
Code:
0: aload_0
1: aload_1
2: putfield #1; //Field this$0:LInnerTest;
5: aload_0
6: iload_2
7: invokespecial #2; //Method Test."<init>":(I)V
10: return

public int getI();
Code:
0: aload_0
1: invokespecial #3; //Method Test.getI:()I
4: bipush 10
6: imul
7: ireturn

}


很明显,我们的匿名内部类有了名字 InnerTest$1 ,而且是继承自 Test
class InnerTest$1 extends Test
这个类中有一个成员final InnerTest this$0;我想这应该是该内部类所在的外部类InnerTest的引用
这个匿名内部类的构造方法是:
InnerTest$1(InnerTest, int);
一个是InnerTest类型,也就是该类外部类的引用,调用的时候应该是把外部类对象的this指针传给它,这样就内部类就可以直接访问外部类的成员了。
另一个就是int类型的,应该是对i进行初始化用的。
看到下面这行:
7: invokespecial #2; //Method Test."<init>":(I)V
现在应该清楚了,这是调用了父类Test的构造方法。
下面再看InnerTest是如何实现的:

Compiled from "Main.java"
class InnerTest extends java.lang.Object{
InnerTest();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return

public Test get(int);
Code:
0: new #2; //class InnerTest$1
3: dup
4: aload_0
5: iload_1
6: invokespecial #3; //Method InnerTest$1."<init>":(LInnerTest;I)V
9: areturn

}

InnerTest的get方法是关键。
这里首先new InnerTest$1,后面调用了InnerTest$1的构造方法,并把两个参数传了进去。
这样一切都清楚了。
结论:其实匿名内部类也没有什么特别的地方,编译之后它有了名字,有了构造方法,就是一个正常的类了。
有理解不对的地方,请大家指正。
...全文
7655 39 打赏 收藏 转发到动态 举报
写回复
用AI写文章
39 条回复
切换为时间正序
请发表友善的回复…
发表回复
JacketLiao 2012-08-19
  • 打赏
  • 举报
回复
看得晕晕的
林翔 2012-08-02
  • 打赏
  • 举报
回复
菜鸟还在进步,谢谢!
baidu321 2012-02-09
  • 打赏
  • 举报
回复
好文,看了受益很多
q8810783 2011-12-01
  • 打赏
  • 举报
回复
[Quote=引用 33 楼 cs_jiang 的回复:]
每天回帖即可获得10分可用分!小技巧
[/Quote]

多谢兄台赐教。
kidomyself 2011-08-30
  • 打赏
  • 举报
回复
还是太菜了,没怎么看懂
super_marioli 2011-06-13
  • 打赏
  • 举报
回复
先顶后看
duoduo_die 2011-01-19
  • 打赏
  • 举报
回复
每天回帖即可获得10分可用分!小技巧
yuhongpingimu 2010-09-02
  • 打赏
  • 举报
回复
怎么觉得编程思想中看过类似的呢。。。
wolf_k_19830724 2008-08-01
  • 打赏
  • 举报
回复
定义在类中的内部类分为实例内部类和静态内部类,实例内部类自动持有外部类的实例的引用,即可以访问外部类的所有变量;静态内部类可以直接访问外部类的静态成员
定义在方法中的内部类叫局部内部类,该类只能访问被final修饰的成员变量和参数

dreamhyz 2008-07-29
  • 打赏
  • 举报
回复
学习了
sjkof 2008-07-29
  • 打赏
  • 举报
回复
学习
finalzhzhk 2008-07-29
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 ZangXT 的回复:]

Java codepublicclassTest {publicSuper getInstance()...
[/Quote]

收到
ZangXT 2008-07-29
  • 打赏
  • 举报
回复
可能我的说法有问题,这是定义在方法中内部类的情形。
ZangXT 2008-07-29
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 finalzhzhk 的回复:]
内部类如果要对外部类中的变量进行访问的话,不需要必须声明为final吧,
可否写个例子,偶想看看是怎么用的
[/Quote]


public class Test {
public Super getInstance(){
int a=5;
final int b=6;
class Inner implements Super{

public void print() {
//内部类中访问外面定义的局部变量
System.out.println(a);//编译错误:Test.java:9: 从内部类中访问局部变量 a;需要被声明为最终类型
System.out.println(b);
}

}
return new Inner();
}
public static void main(String[] args) {
Super s=new Test().getInstance();
s.print();
}
}
interface Super{
public void print();
}

finalzhzhk 2008-07-29
  • 打赏
  • 举报
回复
ZangXT老师的无私精神真值得大家学习啊。

[Quote=引用 15 楼 ZangXT 的回复:]
内部类如果要对外部类中的变量进行访问的话,外部类中相应的变量必须声明为final.
这是内部类的一个语法。
[/Quote]
这个
内部类如果要对外部类中的变量进行访问的话,不需要必须声明为final吧,
可否写个例子,偶想看看是怎么用的
kokobox 2008-07-29
  • 打赏
  • 举报
回复
  • 打赏
  • 举报
回复
嘿嘿
亦风亦尘 2008-07-29
  • 打赏
  • 举报
回复
路过,接点分
ZangXT 2008-07-28
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 llm0528 的回复:]
唉~真不明白,为什么楼主会知道,我却不知道这些东西,而且书上居然都没介绍的
[/Quote]
无聊的时候就自己按 bytecode
zhj92lxs 2008-07-28
  • 打赏
  • 举报
回复
接分
加载更多回复(18)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧