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

 

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:

class testtest.InnerTest$1 extends testtest.Test

而且在这个类有构造方法: 

testtest.InnerTest$1(testtest.InnerTest, int);

这里也很容易理解,两个参数,一个是匿名内部类的外部类引用直接传了进来,这也是我们能在内部类中直接访问外部类成员的实现原理。另外一个就是int类型的参数了。也就是说其实编译器自动的给我们添加了带参数的构造方法。继续往下看: 
7: invokespecial #2; //Method testtest/Test."<init>":(I)V
这就是调用父类的构造方法了 。
接下来 ,我们 只要看 InnerTest中 get方法 的 实现就可以了 :

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>
 


到这里一切都清楚了,InnerTest中对待匿名内部类和对待普通类一样,

先是

0:	new	#2; //class testtest/InnerTest$1

然后调用其构造方法:

6: invokespecial #3; //Method testtest/InnerTest$1."〈init〉":(Ltesttest/InnerTest;I)V
 


<init></init><init>OK,一切都清楚了 。<br></init>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值