需要帮助解释scala问题吗
我有两个scala类(以及使用需要帮助解释scala问题吗,scala,Scala,我有两个scala类(以及使用javap-private读取类文件时的Java代码) 当我在toString方法中使用n和d时,它将在类中生成私有成员字段。为什么呢?我有点困惑 Scala#1: javap的等价物: public class com.zjffdu.tutorial.scala.Rational extends java.lang.Object implements scala.ScalaObject{ public com.zjffdu.tutorial.scala.R
javap-private
读取类文件时的Java代码)
当我在toString
方法中使用n
和d
时,它将在类中生成私有成员字段。为什么呢?我有点困惑
Scala#1:
javap的等价物:
public class com.zjffdu.tutorial.scala.Rational
extends java.lang.Object
implements scala.ScalaObject{
public com.zjffdu.tutorial.scala.Rational(int, int);
}
public class com.zjffdu.tutorial.scala.Rational
extends java.lang.Object
implements scala.ScalaObject{
private final int n;
private final int d;
public java.lang.String toString();
public com.zjffdu.tutorial.scala.Rational(int, int);
}
Scala#2:
javap的等价物:
public class com.zjffdu.tutorial.scala.Rational
extends java.lang.Object
implements scala.ScalaObject{
public com.zjffdu.tutorial.scala.Rational(int, int);
}
public class com.zjffdu.tutorial.scala.Rational
extends java.lang.Object
implements scala.ScalaObject{
private final int n;
private final int d;
public java.lang.String toString();
public com.zjffdu.tutorial.scala.Rational(int, int);
}
嗯,
n
和d
的值需要从toString
主体内部以某种方式提供,对吗?否则你就无法使用它们。当您构造一个新实例时,n
和d
恰好在堆栈上,当您调用toString
时,n
和p
早已从堆栈中消失,这两者之间可能发生任何事情。因此,编译器会自动将值保存在字段中,即使在代码中没有将它们声明为(private)val
s。编译器将对类的构造函数之外使用的所有构造函数变量执行此操作(请记住,类的构造函数实际上是类本身的整体,不包括val
和def
定义)。Scala将采用构造函数参数,即使未声明val
或var
,如果需要在构造函数之外使用它们,也可以将它们作为私有字段添加到类中
在您的情况下,
toString
可以在对象创建后很久调用。因此,这些参数需要存储在构造的实例中。好吧,这里更有趣。如果您尝试以下方法:
class Rational(n: Int, d: Int) {
override val toString = n + "/" + d
}
然后,私人变桨又消失了
public class Rational extends java.lang.Object implements scala.ScalaObject{
private final java.lang.String toString;
public java.lang.String toString();
public Rational(int, int);
}
区别在于,在方法中使用d
和n
时,必须保留它们。如果它们不在方法中使用,只在构造函数中使用(例如val
initialization),则它们不需要作为每个实例的成员存在。查看def-toString
的反编译版本:
public java.lang.String toString();
Code:
0: new #10; //class scala/collection/mutable/StringBuilder
3: dup
4: invokespecial #14; //Method scala/collection/mutable/StringBuilder."<init>":()V
7: aload_0
8: getfield #19; //Field n:I
11: invokevirtual #23; //Method scala/collection/mutable/StringBuilder.append:(I)Lscala/collection/mutable/StringB
uilder;
14: ldc #25; //String /
16: invokevirtual #28; //Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collectio
n/mutable/StringBuilder;
19: aload_0
20: getfield #30; //Field d:I
23: invokestatic #36; //Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
26: invokevirtual #28; //Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collectio
n/mutable/StringBuilder;
29: invokevirtual #38; //Method scala/collection/mutable/StringBuilder.toString:()Ljava/lang/String;
32: areturn
public java.lang.String toString();
代码:
0:新的#10//类scala/collection/mutable/StringBuilder
3:dup
4:特别是#14//方法scala/collection/mutable/StringBuilder。“”:()V
7:aload_0
8:getfield#19//田纳西州:我
11:invokevirtual#23//方法scala/collection/mutable/StringBuilder.append:(I)Lscala/collection/mutable/StringB
造船厂;
14:最不发达国家25//串/
16:invokevirtual#28//方法scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collectio
n/mutable/StringBuilder;
19:aload_0
20:getfield#30//d场:我
23:invokestatic#36//方法scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
26:invokevirtual#28//方法scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collectio
n/mutable/StringBuilder;
29:invokevirtual#38//方法scala/collection/mutable/StringBuilder.toString:()Ljava/lang/String;
32:轮到你了
参见第8行和第20行?如果是
val-toString
而不是def-toString
,会发生同样的事情吗?如果是val-toString
,那么你会看到一个toString
字段。是的,当然,但是n和d的私有字段应该是正确的?soc-确实,您将看到toString
而不是n
和d
,而不是它们。