tags:

views:

225

answers:

4

Are there any practical uses of anonymous code blocks in Java?

public static void main(String[] args) {
    // in
    {
        // out
    }
}

Please note that this is not about named blocks, i.e.

name: { 
     if ( /* something */ ) 
         break name;
}

.

+6  A: 

They restrict variable scope.

public void foo()
{
    {
        int i = 10;
    }
    System.out.println(i); // Won't compile.
}

In practice, though, if you find yourself using such a code block that's probably a sign that you want to refactor that block out to a method.

David Seiler
Good answer, and completely agree with the method comment.
Robert Munteanu
+1: correct answer, and it is a sign of a desperately needed refactor, aka a "code smell" as Martin Fowler puts it :)
aperkins
+4  A: 
OscarRyz
That's actually an instance initialiser, which is a different thing.
Tom Hawtin - tackline
Different to ... ? Constructors? Oh yes, I mean "as substitute or complement to.." when referring to constructor.
OscarRyz
+3  A: 

anonymous blocks are useful for limiting scope of variable as well as for double brace initialization. Compare:

Set<String> validCodes = new HashSet<String>();
validCodes.add("XZ13s");
validCodes.add("AB21/X");
validCodes.add("YYLEX");
validCodes.add("AR2D");

with:

Set<String> validCodes = new HashSet<String>() {{
  add("XZ13s");
  add("AB21/X");
  add("YYLEX");
  add("AR5E");
}});
dfa
+1 but the last parenthesis is superfluous.
LB
+1 just for AR5E
Brian Agnew
Whoah, that double brace initialization stuff is pretty sweet.
StriplingWarrior
Bevare though that in a second instance validCodes now is not a HashSet, but rather a subclass of a HashSet. With more complex classes this can lead to some unexpected behavior.
Alexander Pogrebnyak
Again, instance initialisers are different from blocks.
Tom Hawtin - tackline
I know the double brace initialization trick, but it's not sweet, it's a dirty trick that will thouroughly confuse people who don't know it. Don't use it!
Jesper
+2  A: 

I think you and/or the other answers are confusing two distinct syntactic constructs; namely Instance Initializers and Blocks. (And by the way, a "named block" is really a Labeled Statement, where the Statement happens to be a Block.)

An Instance Initializer is used at the syntactic level of a class member; e.g.

public class Test {
    final int foo;

    {
         // Some complicated initialization sequence; e.g.
         int tmp;
         if (...) {
             ...
             tmp = ...
         } else {
             ...
             tmp = ...
         }
         foo = tmp;
    }
}

The Initializer construct is most commonly used with anonymous classes as per @dfa's example. Another use-case is for doing complicated initialization of 'final' attributes; e.g. see the example above. (However, it is more common to do this using a regular constructor. The pattern above is more commonly used with Static Initializers.)

The other construct is an ordinary block and appears within a code block such as method; e.g.

public void test() {
    int i = 1;
    {
       int j = 2;
       ...
    }
    {
       int j = 3;
       ...
    }
}

Blocks are most commonly used as part of control statements to group a sequence of statements. But when you use them above, they (just) allow you to restrict the visibility of declarations; e.g. j in the above.

This usually indicates that you need to refactor your code, but it is not always clear cut. For example, you sometimes see this sort of thing in interpreters coded in Java. The statements in the switch arms could be factored into separate methods, but this may result in a significant performance hit for the "inner loop" of the interpreter.

    switch (op) {
    case OP1: {
             int tmp = ...;
             // do something
             break;
         }
    case OP2: {
             int tmp = ...;
             // do something else
             break;
         }
    ...
    };
Stephen C