Home > Java > javaTutorial > body text

Constructor call of anonymous inner class in java

高洛峰
Release: 2016-12-15 13:22:35
Original
1989 people have browsed it

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

 

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;  
            }  
        };  
    }  
}
Copy after login

编译之后得到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>
Copy after login

很明显,虽然我们看来是匿名内部类,但编译的时候给这个类指定了名字

InnerTest$1,而且看出来是继承自Test:

Java代码

class testtest.InnerTest$1 extends testtest.Test
Copy after login

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

Java代码

testtest.InnerTest$1(testtest.InnerTest, int);
Copy after login

这里也很容易理解,两个参数,一个是匿名内部类的外部类引用直接传了进来,这也是我们能在内部类中直接访问外部类成员的实现原理。另外一个就是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">
Copy after login

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

先是

Csharp代码

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

然后调用其构造方法:

Java代码

6: invokespecial #3; //Method testtest/InnerTest$1."〈init〉":(Ltesttest/InnerTest;I)V<pre class="brush:php;toolbar:false">
Copy after login

OK,一切都清楚了 。


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

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!