2013-02-20 60 views
1

使用Scala 2.10,以下编译没有错误。为什么scala try块允许重新定义封闭范围的变量?

val test = 1 
try { 
    val test = 2 
} 

望着生成的字节码,我看到:

int test = 1; 
int test = 2; 

这难道不奇怪吗?还是我错过了明显的东西?

+0

它被称为阴影,可以在任何设置中通过在'{'braces'}'中包含一系列表达式来创建新的内部作用域。 – 2013-02-20 14:46:49

+0

我知道这不是真的,但是用Scala我假装'{'和'}'定义了一个函数。这使得我个人更容易理解这些结构。 – EECOLOR 2013-02-20 21:55:28

回答

2

这有什么好做try中存在。变量可以在任何影对方,你可以把块基本上在任何地方:

val x = 0 
if ({val x = 1; x*3}==0) { 
    val x = 2; x + x + x 
} 
else x 

这使得代码更容易移植:你可以自由走动块,而不必担心在外面的东西可能会发生冲突。 (好吧,并不完全正确:哪些隐含在范围内仍然可能会导致问题,但这比重复的变量更不可能让您受到影响。)

这是与Java不同的选择; Java的态度是,你更可能忘记你的变量名称,需要提醒,而斯卡拉的说法是,即使外部环境发生变化,你的意思可能就是你所说的。考虑到Java对可变操作的关注(遮蔽可变变量真的会导致问题!)和Scala的默认不变性(隐藏外部不可变变量可能甚至是可取的,因为您可以重用像i和x这样的短变量到你心中的内容)。

+0

谢谢!我会接受你的回答,因为令我感到困惑的事情是scala和java之间的区别,我认为你提供了一个合理的解释。我在创建一个可变变量时遇到了这个问题,然后不小心将其映射到了我的try块中,而不是将它分配给它。我想我应该看一些处理异常的更习惯的scala模式,:P – zakvdm 2013-02-21 10:01:56

3

局部变量可以始终与具有较宽范围的名称相同。通过将它声明在括号内,可以有效防止意外地使用/覆盖别处使用的变量。不奇怪 - 但有用!

+0

感谢您的回答。尽管如此,还是有一些东西让我困惑......据我所知,这种行为与Java(不同的代码无法编译)不同。为什么这种不一致?这是Scala关闭的自然后果吗?然后就会产生奇怪的字节码......这个字节码如何等同于内部的“测试”实例和外部范围的实例? – zakvdm 2013-02-20 13:58:30

+0

我同意字节码很混乱,因为它没有显示名为“test”的变量的作用域 - 因此看着字节码,如果它们是相同的变量,则无法判断。它是否显示他们有不同的地址? @korefn的例子是否如预测的那样显示“1 2 1”? – Floris 2013-02-20 15:07:49

2

也许你试试这个得到什么在

val test = 1 
println(test) 
try{ 
    val test = 2 
    println(test) 
} 
println(test) 

范围的事项要清晰的画面。我希望你得到了121 第二test只有尝试范围