根据这个例子,对于每个类的实例,someValue的计算只运行一次?
case class MyThing {
def myMethod {
val someValue = 19 * 27
someValue
}
}
相同的规则是否适用于object
object MyObject {
def myMethod {
val someValue = 19 * 27
someValue
}
}
如果你有一个不可变的case类(当然,对象由于是单个实例而是不可变的),那么重新运行已经运行的计算是没有意义的,即使它们在类本身中使用了值(我正在考虑自定义hashCode计算(例如)。
编译器是否足够智能处理或者将val放在def之外会更好吗? (让它变得懒惰所以它只在需要时被调用......)
答案 0 :(得分:2)
文字在编译时内联:
scala> object O { def f = 19*27 }
defined object O
scala> :javap -c O
Compiled from "<console>"
public class O$ {
public int f();
Code:
0: sipush 513
3: ireturn
<snip>
}
通常,当没有涉及文字时,Scala编译器不会优化这种情况:
scala> object O { def f = g*h; def g = 19; def h = 27 }
defined object O
scala> :javap -c O
Compiled from "<console>"
public class O$ {
public int f();
Code:
0: aload_0
1: invokevirtual #17 // Method g:()I
4: aload_0
5: invokevirtual #20 // Method h:()I
8: imul
9: ireturn
public int g();
Code:
0: bipush 19
2: ireturn
public int h();
Code:
0: bipush 27
2: ireturn
<snip>
}
当您编写def
时,您的意思是def
,即每次调用该方法时,都会评估其中的所有内容。任何应该缓存的东西都需要手动完成。
然而,在上面的示例中,JVM本身很可能会内联g
和h
,结果是第一个和第二个示例将针对相同的机器代码进行优化。
答案 1 :(得分:0)
简单地说:不。
val
仅评估一次。
def
。
这是Scala语言中这些关键字之间的区别。
由于myMethod
没有参数且不受副作用影响,因此应将其更改为val
或更改为lazy val
,以便仅在需要时运行。
使用intent进行编程而不是依赖编译器优化会更有效率。