我前几天(在SO上)了解到
public method() {
someCode()
{
Object value = localCode();
doSomethingWith(value);
}
moreCode();
}
是有效的Java,它使包含value
的块在该区域内是本地的,因此value
仅存在于该块中。
这有什么实际用途吗?如果没有,为什么Java没有对这个(愚蠢)使用{}
?
答案 0 :(得分:10)
我在测试中使用它,我想重复不同的场景。
{
long start = System.nanoTime();
// do something
long time = System.nanoTime() - start;
// print result.
}
{
long start = System.nanoTime();
// do something else
long time = System.nanoTime() - start;
// print result.
}
{
long start = System.nanoTime();
// do something else again.
long time = System.nanoTime() - start;
// print result.
}
这允许复制代码而无需更改名称,或冒着重复使用变量的风险。
答案 1 :(得分:3)
不确定这究竟是为什么,但假设以下(有点人为的)senario:
public static void main(String[] args){
int[] idsToCheck = {};
{
ExpensiveIDComputer sic = new ExpensiveIDComputer(); // very memory intensive call
idsToCheck = sic.getIds();
}
// sic is now out of scope and can be GCed faster
doManyOperationsOnIds(idsToCheck);
}
基本上,它允许您启用内存占用操作,以便更快地收集垃圾。为什么你不会只使用另一种方法,我不知道,但这是我第一次想到你的问题。
答案 2 :(得分:1)
...所以moreCode只有该块中的值。
如果未在块内声明moreCode
,则不完全正确。例如:
int moreCode = 0;
{
moreCode = 1;
System.out.println(moreCode);
}
// Will print 1, not 0!
System.out.println(moreCode);
您可以使用它来限制变量的范围。如果在块内声明一个变量,它将只存在于块内。
{
int moreCode = 1;
System.out.println(moreCode);
}
// Compile error: The variable moreCode doesn't exist here
System.out.println(moreCode);
然而,这并不是常用的东西。如果您觉得需要使用块来限制范围,那么您的方法可能过于复杂,您应该考虑将它们拆分为更简单的方法。
答案 3 :(得分:1)
我使用它有三个原因:
最常见的是,在我初始化一个或多个最终值时声明/使用临时值:
final int value;
{
final int counter;
... compute value ...
value = counter;
}
否则“不工作”而不将变量引入外部命名空间(限制范围)。
突出/区分属于一起的代码部分,但我还没准备好推广到一个独立的方法(通常是为了整体的可读性而维护代码的位置)。 [在任何用例的90%中,代码应该被提升 - 这有点特殊]。
答案 4 :(得分:1)
不,如果在{}块之外声明了moreCode
变量,它将保留value
,除非它在执行期间被更改。
初始化块通常不会被使用。
但是当你的类有多个构造函数时,它很棒,它应该做一些常见的初始化操作,比如初始化一些变量或加载一些数据。
您可以将公共构造函数代码粘贴到初始化块中,如下所示。还有一个事实是初始化块只会在构造函数和父构造函数之后执行。
实例变量的初始化块看起来就像静态 初始化块,但没有static关键字:
{
// whatever code is needed for initialization goes here
}
Java编译器将初始化程序块复制到每个构造函数中。 因此,这种方法可用于共享一段代码 多个构造函数。
参考:http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
答案 5 :(得分:0)
示例是instance initializers
,其中代码必须捕获异常。
class SomeClass {
private int myVar;
// Instance initializer
{
try{
myVar = getInitialValueFromDB();
}
catch(Exception e){
myVar = -1;
}
}
// no constructor here
// ...
}
答案 6 :(得分:0)
如果您为代码块命名,则可以通过寻址名称来break
阻止该块。
name1 : {
name2 :{
final int i = 1;
if( i == 1) {
break name1;
}
System.out.println("name2");
}
System.out.println("name1");
}
你也可以limit the scope of a variable
,所以在块结束后变量很容易被垃圾收集。
答案 7 :(得分:0)
它还允许您添加标签,以便您可以制作意大利面条代码!
MY_LABEL: {
if (condition) {
break MY_LABEL;
}
System.out.println("IN BLOCK");
}
System.out.println("OUTSIDE BLOCK");
如果condition
为真,则控制流将跳过第一个打印语句,您将只获得第二个打印。
免责声明: 我不建议使用意大利面条代码 - 这只是对可能对像这一点。
答案 8 :(得分:0)
另一个用例:为匿名子类声明最终变量。显然,你不能只在下面的匿名子类中引用“foo”。你必须让它“最终”。作为替代方案,我们将值复制到新的最终变量中并使用它。新变量是执行期间特定时间点的“foo”快照值。
int foo = 1;
....
{
final int bar = foo;
Future<Void> future = executorService.submit(new Callable<Void>() { // use bar here });
}
我意识到你可以在没有大括号的情况下做到这一点,但这限制了新变量的范围。