79

I have some Java code that uses curly braces in two ways

// 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);

What do those stand-alone curly braces after the first if statement mean?

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Paul Wicks
  • 55,730
  • 52
  • 115
  • 144

11 Answers11

120

The only purpose of the extra braces is to provide scope-limit. The List<PExp> copy will only exist within those braces, and will have no scope outside of them.

If this is generated code, I assume the code-generator does this so it can insert some code (such as this) without having to worry about how many times it has inserted a List<PExp> copy and without having to worry about possibly renaming the variables if this snippet is inserted into the same method more than once.

matt b
  • 132,562
  • 64
  • 267
  • 334
  • 9
    An additional "benefit" in this case is that `copy` can be garbage collected before `outAMethodExp()` returns. If this is a long-running or memory-intensive call, that may be helpful. I put "benefit" in quotes because refactoring into separate methods is generally much cleaner and clearer than taking advantage of this syntax. – dimo414 Feb 16 '15 at 21:56
  • 1
    Actually, scoping a variable does **not** have an effect on garbage collection. In all modern JVMs I'm aware of, the JIT can determine that an object is eligible for GC regardless of the presence or absence of scoping constructs like braces. – Daniel Pryden Oct 19 '16 at 09:46
27

I second what matt b wrote, and I'll add that another use I've seen of anonymous braces is to declare an implicit constructor in anonymous classes. For example:

  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");
      }

  };

Some unit-testing frameworks have taken this syntax to another level, which does allow some slick things which look totally uncompilable to work. Since they look unfamiliar, I am not such a big fan myself, but it is worthwhile to at least recognize what is going on if you run across this use.

Dov Wasserman
  • 2,536
  • 16
  • 13
  • I am sorry, I don't understand this code. Is "add" a class or a function. If it is a function: what class does it belong to? Is ArrayList accepting a delegate type in this case? – Peter Mortensen Aug 03 '09 at 18:50
  • 7
    "add" is a function. The stuff within the curly braces gets called before the constructor to perform some preliminary initialization. You can check out http://www.c2.com/cgi/wiki?DoubleBraceInitialization for more. – Zaven Nahapetyan Dec 17 '10 at 00:34
  • 1
    Technically, the constructor gets called first and the instance initialization block gets called immediately after the call to `super(...)`. – Oli Mar 30 '15 at 11:14
8

I agree with the scope limit answer, but would add one thing.

Sometimes you see a construct like that in the code of people who like to fold sections of their code and have editors that will fold braces automatically. They use it to fold up their code in logical sections that don't fall into a function, class, loop, etc. that would usually be folded up.

Eli
  • 88,788
  • 20
  • 72
  • 81
4

I'd actually guess that someone forgot an else statement.

There's rarely a good reason to even bother with creating additional block scopes. In this, and most cases, it's far more likely someone may have forgotten to type their control statement than it is that they were doing something clever.

halfer
  • 18,701
  • 13
  • 79
  • 158
Patrick
  • 81,802
  • 10
  • 48
  • 61
  • 2
    I'm voting you up simply because it can happen, has happened, and Occam is rolling in his grave because you were voted down. :) – willasaywhat Oct 27 '08 at 19:53
  • 1
    It is generated by SableCC. I bet 5$ they did not forget else – Pavel Feldman Oct 27 '08 at 20:47
  • Additional braces are useful for preventing global variables from creeping up on you in a long method where you want to keep a few, similar code blocks all in the same spot, where the blocks aren't complex enough to warrant new methods. – jayunit100 Dec 06 '11 at 19:21
  • I mark java coursework at a university, and can see that this is actually often the exact reason why it is found in code. When re factoring people sometimes cut/paste and then see the wrong number of braces,.. just add one in.. then look what you end up with. For that reason I am up voting this. Not always an else statement, but often just a simple mistake. – ThePerson Mar 14 '13 at 12:05
  • I upvoted you because -1 votes means you should not have even participated. Maybe you didn't know, but you put in an effort. I'm not about trophies for everyone, but "thanks" is just what I say to people who are trying to help. (+1 == thanks). – user426364 Jul 02 '14 at 18:47
  • Although in this case, it isn't true (generated code), I'm sure IRL this happens a lot, so +1 – k_g Apr 03 '15 at 20:06
  • I do programming for a living for almost 18 years now. I have not a single time seen someone forgetting a control statement - not in student homeworks, mind you. "There's rarely a good reason ..." is rightout misleading - sometimes scoping is more readable than refactoring to separate methods. Plus, you might want to scope some locals and not others. Without scoping, you end up with "creative" naming, such as tmpList1, tmpList2 etc. – user625488 Jan 29 '16 at 16:18
2

They make an inner scope. Variable declared inside these braces is not visible outside of them. This also applies to C/C++.

Paweł Hajdan
  • 16,853
  • 9
  • 45
  • 63
1

Braces are also useful to reduce the scope in switch/case statements.

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

But you can write

switch(foo) {
  case BAR:{
     int i = ...
     ...
  }
  case BAZ:{
     int i = ... // OK
  }
}
Philipp
  • 4,301
  • 7
  • 37
  • 62
1

It is also used for initialization blocks.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Gabriel
  • 1,468
  • 2
  • 13
  • 33
  • Probably worth mentioning that this is only for static class initialization outside the constructor. OPs code snippet is in a method block (only possible place for it). – mmoore Mar 14 '13 at 18:39
  • An initialization block is for static class initialization if it is prefaced with `static` otherwise its an _instance_ initialization block. – Gabriel Mar 14 '13 at 22:29
0

I think they just define an unnamed level of scope.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
0

They define a new scope which means that everything declared in this scope is not visible outside the curly braces.

fhe
  • 5,847
  • 1
  • 37
  • 40
0

The bring a scope, copy will not be visible outside of it, so you can declare another variable with same name later. And it can be gathered by the garbage collector right after you exit that scope. In this case copy serves as a temporary variable, so it is a good example.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Pavel Feldman
  • 4,361
  • 5
  • 28
  • 31
0

As an interesting note: the braces actually enable a class of statements: declarations.

This is illegal: if(a) int f;

but this is legal: if(a) { int f; }

Hugo
  • 3,801
  • 1
  • 27
  • 31
  • Exactly this code is useless, you will not be able to see f outside of braces. And to use it you need to declare and use it inside same scope. So you need more than one statement, so you need braces. – Pavel Feldman Oct 27 '08 at 21:46
  • that's the point of the compiler check that i'm mentioning. I find it interesting that there is a difference in "implicit scope" (which i consider each one-liner without braces to be) and explicit ones. It's easy to forget that the compiler would make a difference. – Hugo Oct 28 '08 at 02:08
  • What about if (userWantsTocInReport) { new Toc(report}; }? I'm not saying it's the ideal way to write it, but it's a possibility someone may choose, for whatever reason. – user625488 Jan 29 '16 at 16:26