我在 Scala 中将特征定义为
trait checkTrait
{
val name:String = "male"
}
据我了解,当在 Scala 类中声明 val 时,仅生成访问器,但是当我使用 JAD 反编译器反编译上面的代码时,会生成以下代码
public interface checkTrait
{
public abstract void checkTrait$_setter_$name_$eq(String s);
public abstract String name();
}
无法理解“checkTrait$setter$name_$eq(String s)”到底是什么 是变异者吗?如果是 Mutator 那么它们是如何生成的,因为根据语言规范,不会为 Vals 生成 Mutator
最佳答案
是的,你说得对。 checkTrait$setter$name_$eq(String s)
是一个用于初始化设置 name
值的 Mutator 方法。
这是由于 Scala 特征 将转换为 Java 接口(interface),并且由于 Java interface
字段是 隐式静态和最终
,但在Scala
中,trait
字段需要是class
或instance<的字段
。因此这个 Mutator 方法 用于初始化 checkTrait
子类的字段。
Java 8 (pre-release) interface member variables
完整说明:
在反编译时,Scala Compiler将trait
checkTrait
转换为Java' s 接口(interface)
。为此反编译应该在checkTrait
中有另一个staticinit
方法,例如:
public interface checkTrait {
public abstract void checkTrait$_setter_$name_$eq(java.lang.String);
public abstract java.lang.String name();
public static void $init$(checkTrait);
Code:
1: ldc #18 // String male
3: invokeinterface #20, 2 // InterfaceMethod checkTrait$_setter_$name_$eq:(Ljava/lang/String;)V
8: return
}
如您所见,这是一个接受 checkTrait
实例参数的静态 init 方法。并调用checkTrait$_setter_$name_$eq
这个mutator方法来初始设置值,值为:male。
让我们尝试扩展
checkTrait
:
class A extends checkTrait
并反编译这个A
类:
public class A implements checkTrait {
public java.lang.String name();
Code:
0: aload_0
1: getfield #15 // Field name:Ljava/lang/String;
4: areturn
public void checkTrait$_setter_$name_$eq(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #15 // Field name:Ljava/lang/String;
5: return
public A();
Code:
0: aload_0
1: invokespecial #24 // Method java/lang/Object."<init>":()V
4: aload_0
5: invokestatic #28 // InterfaceMethod checkTrait.$init$:(LcheckTrait;)V
8: return
}
我们可以发现,在A
的构造方法中,它会通过以下方式调用checkTrait
static init
方法:
5: invokestatic #28 // InterfaceMethod checkTrait.$init$:(LcheckTrait;)V
将当前实例传递给初始化name
字段值。
这就是在 trait 中实现字段的 Scala 方式。
关于scala - 在 Scala Trait 中使用 Val,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43446423/