81

我有一些 Java 代码以两种方式使用花括号

// Curly braces attached to an 'if' statement:
if(node.getId() != null)
{
    node.getId().apply(this);
}

// Curly braces by themselves:
{
    List<PExp> copy = new ArrayList<PExp>(node.getArgs());
    for(PExp e : copy)
    {
        e.apply(this);
    }
}
outAMethodExp(node);

第一个语句之后的那些独立的花括号if是什么意思?

4

11 回答 11

122

额外大括号的唯一目的是提供范围限制。将List<PExp> copy只存在于这些大括号中,并且在它们之外没有范围。

如果这是生成的代码,我假设代码生成器会这样做,因此它可以插入一些代码(例如这个),而不必担心它插入了多少次 aList<PExp> copy并且不必担心如果这个片段可能重命名变量多次插入同一个方法。

于 2008-10-27T19:15:40.553 回答
27

我支持 matt b 所写的内容,并且我将补充一点,我看到的匿名大括号的另一个用途是在匿名类中声明一个隐式构造函数。例如:

  List<String> names = new ArrayList<String>() {
    // I want to initialize this ArrayList instace in-line,
    // but I can't define a constructor for an anonymous class:
      {
        add("Adam");
        add("Eve");
      }

  };

一些单元测试框架已经将这种语法提升到了另一个层次,它确实允许一些看起来完全无法编译的巧妙的东西工作。由于它们看起来不熟悉,因此我自己并不是那么大的粉丝,但是如果您遇到这种用法,至少要认识到发生了什么是值得的。

于 2008-10-28T01:17:13.070 回答
8

我同意范围限制的答案,但会添加一件事。

有时你会在喜欢折叠部分代码并拥有可以自动折叠大括号的编辑器的代码中看到类似的结构。他们使用它将代码折叠在不属于通常会折叠的函数、类、循环等的逻辑部分中。

于 2008-10-28T01:21:22.937 回答
5

我实际上猜想有人忘记了 else 声明。

很少有充分的理由去创建额外的块作用域。在这种情况下,大多数情况下,与他们正在做一些聪明的事情相比,有人可能忘记输入他们的控制语句的可能性要大得多。

于 2008-10-27T19:18:03.810 回答
2

他们制作了一个内部范围。在这些大括号内声明的变量在它们之外是不可见的。这也适用于 C/C++。

于 2008-10-27T19:14:22.897 回答
1

它也用于初始化块

于 2010-12-16T22:39:56.973 回答
1

大括号对于缩小 switch/case 语句的范围也很有用。

switch(foo) {
  case BAR:
     int i = ...
     ...
  case BAZ:
     int i = ... // error, "i" already defined in scope
}

但是你可以写

switch(foo) {
  case BAR:{
     int i = ...
     ...
  }
  case BAZ:{
     int i = ... // OK
  }
}
于 2015-03-16T10:23:08.227 回答
0

我认为他们只是定义了一个未命名的范围级别。

于 2008-10-27T19:14:51.290 回答
0

他们定义了一个新的范围,这意味着在这个范围内声明的所有内容在花括号之外都是不可见的。

于 2008-10-27T19:15:15.813 回答
0

带一个作用域,副本在它之外将不可见,因此您可以稍后声明另一个具有相同名称的变量。它可以在您退出该范围后立即由垃圾收集器收集。在这种情况下,副本用作临时变量,所以它是一个很好的例子。

于 2008-10-27T19:18:04.060 回答
0

作为一个有趣的说明:大括号实际上启用了一类语句:声明。

这是非法的:if(a) int f;

但这是合法的:if(a) { int f; }

于 2008-10-27T19:47:27.730 回答