[ACCEPTED]-Anonymous code blocks in Java-java

Accepted answer
Score: 136

They restrict variable scope.

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

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

Score: 48

@David Seiler's answer is right, but I would 19 contend that code blocks are very useful 18 and should be used frequently and don't 17 necessarily indicate the need to factor 16 out into a method. I find they are particularly 15 useful for constructing Swing Component 14 trees, e.g:

JPanel mainPanel = new JPanel(new BorderLayout());
{
    JLabel centerLabel = new JLabel();
    centerLabel.setText("Hello World");
    mainPanel.add(centerLabel, BorderLayout.CENTER);
}
{
    JPanel southPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0,0));
    {
        JLabel label1 = new JLabel();
        label1.setText("Hello");
        southPanel.add(label1);
    }
    {
        JLabel label2 = new JLabel();
        label2.setText("World");
        southPanel.add(label2);
    }
    mainPanel.add(southPanel, BorderLayout.SOUTH);
}

Not only do the code blocks limit 13 the scope of variables as tightly as possible 12 (which is always good, especially when dealing 11 with mutable state and non-final variables), but 10 they also illustrate the component hierarchy 9 much in the way as XML / HTML making the 8 code easier to read, write and maintain.

My 7 issue with factoring out each component 6 instantiation into a method is that

  1. The method will only be used once yet exposed to a wider audience, even if it is a private instance method.
  2. It's harder to read, imagining a deeper more complex component tree, you'd have to drill down to find the code you're interested, and then loose visual context.

In this 5 Swing example, I find that when complexity 4 really does grow beyond manageability it 3 indicates that it's time to factor out a 2 branch of the tree into a new class rather 1 than a bunch of small methods.

Score: 24

It's usually best to make the scope of local variables as small as possible. Anonymous code blocks 13 can help with this.

I find this especially 12 useful with switch statements. Consider the following 11 example, without anonymous code blocks:

public String manipulate(Mode mode) {
    switch(mode) {
    case FOO: 
        String result = foo();
        tweak(result);
        return result;
    case BAR: 
        String result = bar();  // Compiler error
        twiddle(result);
        return result;
    case BAZ: 
        String rsult = bar();   // Whoops, typo!
        twang(result);  // No compiler error
        return result;
    }
}

And 10 with anonymous code blocks:

public String manipulate(Mode mode) {
    switch(mode) {
        case FOO: {
            String result = foo();
            tweak(result);
            return result;
        }
        case BAR: {
            String result = bar();  // No compiler error
            twiddle(result);
            return result;
        }
        case BAZ: {
            String rsult = bar();   // Whoops, typo!
            twang(result);  // Compiler error
            return result;
        }
    }
}

I consider the 9 second version to be cleaner and easier 8 to read. And, it reduces the scope of variables 7 declared within the switch to the case to 6 which they were declared, which in my experience 5 is what you want 99% of the time anyways.

Be 4 warned however, it does not change the behavior 3 for case fall-through - you'll still need 2 to remember to include a break or return to prevent 1 it!

Score: 18

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

An Instance Initializer is 23 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 22 Initializer construct is most commonly used 21 with anonymous classes as per @dfa's example. Another 20 use-case is for doing complicated initialization 19 of 'final' attributes; e.g. see the example 18 above. (However, it is more common to do 17 this using a regular constructor. The pattern 16 above is more commonly used with Static 15 Initializers.)

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

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

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

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

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

You may use it as constructor for anonymous 5 inner classes.

Like this:

alt text

This way you can 4 initialize your object, since the free block 3 is executed during the object construction.

It 2 is not restricted to anonymous inner classes, it 1 applies to regular classes too.

public class SomeClass {
    public List data;{
        data = new ArrayList();
        data.add(1);
        data.add(1);
        data.add(1);
    }
}
Score: 7

Anonymous blocks are useful for limiting 1 the scope of a 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");
}};
Score: 2

Instance initializer block:

class Test {
    // this line of code is executed whenever a new instance of Test is created
    { System.out.println("Instance created!"); }

    public static void main() {
        new Test(); // prints "Instance created!"
        new Test(); // prints "Instance created!"
    }
}

Anonymous initializer block:

class Test {

    class Main {
        public void method() {
            System.out.println("Test method");
        }
    }

    public static void main(String[] args) {
        new Test().new Main() {
            {
                method(); // prints "Test method"
            }
        };

        {
            //=========================================================================
            // which means you can even create a List using double brace
            List<String> list = new ArrayList<>() {
                {
                    add("el1");
                    add("el2");
                }
            };
            System.out.println(list); // prints [el1, el2]
        }

        {
            //==========================================================================
            // you can even create your own methods for your anonymous class and use them
            List<String> list = new ArrayList<String>() {
                private void myCustomMethod(String s1, String s2) {
                    add(s1);
                    add(s2);
                }

                {
                    myCustomMethod("el3", "el4");
                }
            };

            System.out.println(list); // prints [el3, el4]
        }
    }
}

Variable scope restrict:

class Test {
    public static void main() {
        { int i = 20; }
        System.out.println(i); // error
    }
}

0

Score: 0

You can use a block to initialize a final 8 variable from the parent scope. This a nice 7 way to limit the scope of some variables 6 only used to initialize the single variable.

public void test(final int x) {
    final ClassA a;
    final ClassB b;
    {
        final ClassC parmC = getC(x);
        a = parmC.getA();
        b = parmC.getB();
    }
    //... a and b are initialized
}

In 5 general it's preferable to move the block 4 into a method, but this syntax can be nice 3 for one-off cases when multiple variables 2 need to be returned and you don't want to 1 create a wrapper class.

Score: 0

I use the anonymous blocks for all the reasons 9 explained in other answers, which boils 8 down to limiting the scope of variables. I 7 also use them to have proper delimitation 6 of pairs of method belonging together.

Consider 5 the following excerpt:

jg.writeStartObject();
{
  jg.writeStringField("fieldName", ((JsonFormFieldDependencyData.FieldLocator) valueOrLocator).getFieldName());
  jg.writeStringField("kind", "field");
}
jg.writeEndObject();

Not only you can see 4 at a glance that the methods are properly 3 paired, but doesn't also kind of look like 2 the output too ?

Just be careful to not abuse 1 it and end up in-lining methods ^^

More Related questions