Java中未指定的块是否有实际用途?

时间:2012-08-15 14:18:49

标签: java block

  

可能重复:
  Anonymous code blocks in Java

我前几天(在SO上)了解到

public method() {
    someCode()
    {
        Object value = localCode();
        doSomethingWith(value);
    }
    moreCode();
}

是有效的Java,它使包含value的块在该区域内是本地的,因此value仅存在于该块中。

这有什么实际用途吗?如果没有,为什么Java没有对这个(愚蠢)使用{}

发出警告

9 个答案:

答案 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 });
}

我意识到你可以在没有大括号的情况下做到这一点,但这限制了新变量的范围。