trait TestTrait1 {
def foo1() = {println ("foo1")};
}
上次讲scala基础的时候提到过特质(trait),这是一个胖接口,可以实现类似多继承的东西。
但一直很好奇这是怎么编译成class并让jvm顺利执行。
经过网上提问无果后,只能自己找答案了。
首先发现trait编译后是两个class文件,如:
- trait TestTrait1 {
- def foo1() = {println ("foo1")};
- }
编译后:
TestTrait1.class和TestTrait1$class.class
经过javap -verbose后发现两个文件分别为interface和class。
TestTrait1.class(只列出关键部分)
- public interface org.ww.test.TestTrait1 extends scala.ScalaObject
- SourceFile: "TestTrait1.scala"
- 。。。。。。。。。。。省略。。。。。。。。。。
- {
- public abstract void foo1();
- }
可以看出,这就是一个java的接口
而TestTrait1$class.class
- public abstract class org.ww.test.TestTrait1$class extends java.lang.Object
- SourceFile: "TestTrait1.scala"
- 。。。。。省略。。。。。。。
- {
- public static void foo1(org.ww.test.TestTrait1);
- Code:
- Stack=2, Locals=1, Args_size=1
- 0: getstatic #11; //Field scala/Predef$.MODULE$:Lscala/Predef$;
- 3: ldc #13; //String foo1
- 5: invokevirtual #17; //Method scala/Predef$.println:(Ljava/lang/Object;
- V
- 8: return
- LineNumberTable:
- line 4: 0
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 9 0 $this Lorg/ww/test/TestTrait1;
- public static void $init$(org.ww.test.TestTrait1);
- Code:
- Stack=0, Locals=1, Args_size=1
- 0: return
- LineNumberTable:
- line 3: 0
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 1 0 $this Lorg/ww/test/TestTrait1;
可见,一个trait会编译成一个接口和一个实现类,而trait的实现会放在类中当做静态方法。
编译的时候,把实现trait的子类编译成实现trait接口的类,是实现就是调用trait静态方法
这回可以理解了吧。
慢着。。。。
好像漏了点什么。。。。
public static void $init$(TestTrait1 $this)是什么?
看名字就知道了,是在初始化实现类的时候调用trait的初始化方法,实际上就是trait的无参构造函数
到这里,关于trait在jvm的实现应该有了一个大致的了解。
对于学习scala语言来说,这种程度应该可以了,如果想有更深的了解的话,建议去看看scala的源码
原文:http://suigara.iteye.com/blog/1674880