你认为打印出来的是什么?
val foo: String = "foo" + foo
println(foo)
val foo2: Int = 3 + foo2
println(foo2)
答案:
foonull
3
为什么呢?规范中是否有一部分描述/解释了这一点?
编辑:为了澄清我的惊讶 - 我确实认识到foo
val foo: String = "foo" + foo
未定义,这就是为什么它有一个默认值null
(整数为零)。但这看起来并不是很干净,而且我认为这里的意见与我一致。我希望编译器能阻止我做那样的事情。它在某些特定情况下确实有意义,例如在定义Stream
本质上是懒惰的时候,但对于字符串和整数,我会期望由于重新分配给val或者告诉我我没有阻止我尝试使用未定义的值,就像我写val foo = whatever
一样(假设whatever
从未定义过)。
为了使事情进一步复杂化,@ dk14指出这种行为仅适用于表示为字段的值,并且不会在块内发生,例如
val bar: String = {
val foo: String = "foo" + foo // error: forward reference extends...
"bar"
}
答案 0 :(得分:11)
答案 1 :(得分:1)
Scala的Int
由下面的基本类型(int
)支持,其默认值(在初始化之前)为0。
另一方面,String
是Object
,未初始化时确实为null
。
答案 2 :(得分:1)
在这两种情况下foo
分别为foo2
根据JVM规范具有默认值。对于引用类型,null
为0
或int
Int
,因为Scala会对其进行拼写。
答案 3 :(得分:1)
不幸的是,scala并不像Haskell那样安全,因为Java的OOP模型(“面向对象满足功能”)有所妥协。有一个安全的Scala子集Scalazzi,一些sbt / scalac-plugins可以给你更多的警告/错误:
https://github.com/puffnfresh/wartremover(doesn't check代表你发现的情况)
回到你的情况,这只发生在表示为字段的值时,并且当你在函数/方法/块中时不会发生:
int main() {
string phrasesAndWords[6];
cin >> phrasesAndWords[0] >> phrasesAndWords[1] >> phrasesAndWords[2] >> phrasesAndWords[3] >> phrasesAndWords[4] >> phrasesAndWords[5]; // Recieve input
int counter = 0;
while (counter < 6) {
switch(phrasesAndWords[counter]) {
case "RandomString":
print("That sure was quite random. \n")
default:
print("I don't understaahnd... \n")
};
counter++;
};
这种情况的原因是与Java的集成scala> val foo2: Int = 3 + foo2
foo2: Int = 3
scala> {val foo2: Int = 3 + foo2 }
<console>:14: error: forward reference extends over definition of value foo2
{val foo2: Int = 3 + foo2 }
^
scala> def method = {val a: Int = 3 + a}
<console>:12: error: forward reference extends over definition of value a
def method = {val a: Int = 3 + a}
编译到JVM中的val
字段,因此Scala保存了JVM类的所有初始化细节(我相信它是JSR-133的一部分:Java记忆模型)。以下是解释此行为的更复杂的示例:
final
所以,在这里你可以看到你没有看到的警告。