需要帮助来解释scala问题
问题描述:
我有两个scala类(以及他们的Java代码,当我使用javap -private
来读取类文件时)。需要帮助来解释scala问题
当我在toString
方法中使用n
和d
时,它将在类中生成私有成员字段。这是为什么?我有点困惑。
Scala的#1:
class Rational(n: Int, d: Int) {
}
等效从javap的:
public class com.zjffdu.tutorial.scala.Rational
extends java.lang.Object
implements scala.ScalaObject{
public com.zjffdu.tutorial.scala.Rational(int, int);
}
Scala的#2:
class Rational(n: Int, d: Int) {
override def toString() = n + "/" + d
}
从javap的当量:
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
和很早就从堆栈中消失之间可能发生任何事情。因此,编译器会自动将值保存在字段中 - 即使您未在代码中将它们声明为(private) val
。编译器会为所有在类的构造函数之外使用的构造函数变量这样做(请记住,类的构造函数实际上是类本身的整体,不包括val
和def
定义)。
答
即使没有声明val
或var
,Scala也会使用构造函数参数,并将它们作为私有字段添加到类中,前提是它们需要在构造函数之外使用。
在你的情况下,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
初始化),则它们不需要作为每个实例的成员存在。看看的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
见8号线和20?
当val toString而不是'def toString'时会发生同样的事情吗? – soc 2011-06-04 14:07:30
如果它是'val toString',那么你会看到'toString'字段。 – 2011-06-04 14:15:43
是的,当然,但那么n和d的私人领域应该是正确的? – soc 2011-06-04 14:44:56