Heim > Java > javaLernprogramm > Konstruktoraufruf einer anonymen inneren Klasse in Java

Konstruktoraufruf einer anonymen inneren Klasse in Java

高洛峰
Freigeben: 2016-12-15 13:22:35
Original
2041 Leute haben es durchsucht

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

 

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;  
            }  
        };  
    }  
}
Nach dem Login kopieren

编译之后得到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>
Nach dem Login kopieren

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

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

Java代码

class testtest.InnerTest$1 extends testtest.Test
Nach dem Login kopieren

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

Java代码

testtest.InnerTest$1(testtest.InnerTest, int);
Nach dem Login kopieren

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

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

先是

Csharp代码

0:  new #2; //class testtest/InnerTest$1
Nach dem Login kopieren

然后调用其构造方法:

Java代码

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

OK,一切都清楚了 。


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

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage