与人讨论匿名内部类的构造方法问题,自己写代码看看原理到底是什么样子的。因为类是匿名的,所以就无从创建一个同名的构造方法了。但是可以直接调用父类的构造方法。测试代码如下:
Java代码
package testtest;
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文件:Test.class,InnerTest.class,InnerTest$1.class以及Main.class。容易看出来,Main.class是测试类的class文件,Test.class是超类Test的class文件,InnerTest.class是InnerTest 的class文件,最值得关注的就是匿名内部类的class文件InnerTest$1.class。
首先javap -c InnerTest$1
立即学习“Java免费学习笔记(深入)”;
Java代码
Compiled from "Main.java"
class testtest.InnerTest$1 extends testtest.Test{
final testtest.InnerTest this$0;
testtest.InnerTest$1(testtest.InnerTest, int);
Code:
0: aload_0
1: aload_1
2: putfield #1; //Field this$0:Ltesttest/InnerTest;
5: aload_0
6: iload_2
7: invokespecial #2; //Method testtest/Test."<init>〈init〉":(I)V
10: return
public int getI();
Code:
0: aload_0
1: invokespecial #3; //Method testtest/Test.getI:()I
4: bipush 10
6: imul
7: ireturn
}
</init>很明显,虽然我们看来是匿名内部类,但编译的时候给这个类指定了名字
InnerTest$1,而且看出来是继承自Test:
Java代码
class testtest.InnerTest$1 extends testtest.Test
而且在这个类有构造方法:
本系统经过多次升级改造,系统内核经过多次优化组合,已经具备相对比较方便快捷的个性化定制的特性,用户部署完毕以后,按照自己的运营要求,可实现快速定制会费管理,支持在线缴费和退费功能财富中心,管理会员的诚信度数据单客户多用户登录管理全部信息支持审批和排名不同的会员级别有不同的信息发布权限企业站单独生成,企业自主决定更新企业站信息留言、询价、报价统一管理,分系统查看分类信息参数化管理,支持多样分类信息,
0
Java代码
testtest.InnerTest$1(testtest.InnerTest, int);
这里也很容易理解,两个参数,一个是匿名内部类的外部类引用直接传了进来,这也是我们能在内部类中直接访问外部类成员的实现原理。另外一个就是int类型的参数了。也就是说其实编译器自动的给我们添加了带参数的构造方法。继续往下看:
7: invokespecial #2; //Method testtest/Test."<init>":(I)V
这就是调用父类的构造方法了 。
接下来 ,我们 只要看 InnerTest中 get方法 的 实现就可以了 :
Csharp代码
Compiled from "Main.java"
class testtest.InnerTest extends java.lang.Object{
testtest.InnerTest();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>〈init〉":()V
4: return
public testtest.Test get(int);
Code:
0: new #2; //class testtest/InnerTest$1
3: dup
4: aload_0
5: iload_1
6: invokespecial #3; //Method testtest/InnerTest$1."<init>〈init〉":(Ltesttest/InnerTest;I)V
9: areturn
}
</init></init><pre></pre>到这里一切都清楚了,InnerTest中对待匿名内部类和对待普通类一样,
先是
Csharp代码
0: new #2; //class testtest/InnerTest$1
然后调用其构造方法:
Java代码
6: invokespecial #3; //Method testtest/InnerTest$1."〈init〉":(Ltesttest/InnerTest;I)V<pre></pre>
<init></init><init>OK,一切都清楚了 。<br></init>
更多java中匿名内部类的构造方法调用相关文章请关注PHP中文网!
java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号