首页 > Java > java教程 > java中匿名内部类的构造方法调用

java中匿名内部类的构造方法调用

高洛峰
发布: 2016-12-15 13:22:35
原创
2041 人浏览过

     与人讨论匿名内部类的构造方法问题,自己写代码看看原理到底是什么样子的。因为类是匿名的,所以就无从创建一个同名的构造方法了。但是可以直接调用父类的构造方法。测试代码如下:

 

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代码

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
登录后复制

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

Java代码

testtest.InnerTest$1(testtest.InnerTest, int);
登录后复制

这里也很容易理解,两个参数,一个是匿名内部类的外部类引用直接传了进来,这也是我们能在内部类中直接访问外部类成员的实现原理。另外一个就是int类型的参数了。也就是说其实编译器自动的给我们添加了带参数的构造方法。继续往下看: 
7: invokespecial #2; //Method testtest/Test."":(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 class="brush:php;toolbar:false">
登录后复制

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

先是

Csharp代码

0:  new #2; //class testtest/InnerTest$1
登录后复制

然后调用其构造方法:

Java代码

6: invokespecial #3; //Method testtest/InnerTest$1."〈init〉":(Ltesttest/InnerTest;I)V<pre class="brush:php;toolbar:false">
登录后复制

OK,一切都清楚了 。


更多java中匿名内部类的构造方法调用相关文章请关注PHP中文网!

相关标签:
来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板