0

Possible Duplicate:
Anonymous code blocks in Java

I learned the other day (on SO) that

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

Is valid Java and it makes the block containing value local to that region, so value only exists in that block.

Is there any practical use for this? If not, why doesn't Java give a warning for this (silly) use of {}?

Community
  • 1
  • 1
AncientSwordRage
  • 7,086
  • 19
  • 90
  • 173

9 Answers9

10

I use this in tests where I want to repeat different scenarios.

{
    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.
}

This allows be to copy the code without having to change the names, or risk re-using variables.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
3

Not sure that this is actually why, but suppose the following (somewhat contrived) 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);
}

So essentially, it would allow you to enable memory-hogging operations to be garbage collected faster. Why you wouldn't just use another method, I don't know, but this was my first thought upon reading your question.

dimo414
  • 47,227
  • 18
  • 148
  • 244
  • Like I said, it's a somewhat contrived example. That said, imagine if you had to construct a large number of expensive objects - perhaps it would be easier to limit their scope than manually ensure you set them all to null. – dimo414 Aug 15 '12 at 15:08
1

... so moreCode only has the value of value in that block.

That's not exactly correct, if moreCode is not declared inside the block. For example:

int moreCode = 0;

{
    moreCode = 1;
    System.out.println(moreCode);
}

// Will print 1, not 0!
System.out.println(moreCode);

You can use this to limit the scope of variables. If you declare a variable inside the block, it will only exist inside the block.

{
    int moreCode = 1;
    System.out.println(moreCode);
}

// Compile error: The variable moreCode doesn't exist here
System.out.println(moreCode);

This is, however, not something that is commonly used. If you feel that you need to use blocks for limiting scope in this way, then your methods are probably too complicated and you should consider splitting them up into simpler methods.

Jesper
  • 202,709
  • 46
  • 318
  • 350
1

I use this for three reasons:

  • Most frequently, to declare/use temporary values, while I'm initializing one or more final values:

    final int value;
    {
       final int counter;
       ... compute value ...
      value = counter;
    }
    
  • To otherwise "do work" without introducing variables into the outer namespace (limit scope).

  • To highlight/distinguish a section of code that belongs together, but I'm not yet ready to promote to an independent method (generally to maintain locality of the code for readability of the whole). [In 90% of any use-case, the code should be promoted - this somewhat exceptional].

Richard Sitze
  • 8,262
  • 3
  • 36
  • 48
1

No, if moreCode variable was declared outside the { } block, it will retain value unless its changed during execution.

Initialization blocks don't get used that often.

But its great to have when your class has multiple constructors, which should do some common initialization operations like initializing some variables or load some data.

You can paste the common constructor code into the initialization block like shown below. There is also the fact that initialization block will only be executed after the constructor and parent constructor.

Initializer blocks for instance variables look just like static initializer blocks, but without the static keyword:

{

// whatever code is needed for initialization goes here 

}

The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.

Reference: http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html

Sreenath S
  • 1,269
  • 1
  • 14
  • 21
0

Example would be instance initializers where code must catch exceptions.

class SomeClass {
    private int myVar;

    // Instance initializer
    {
        try{ 
           myVar = getInitialValueFromDB(); 
        }  
        catch(Exception e){
           myVar = -1;
        }       
    }
    // no constructor here
    // ...
}
Cratylus
  • 52,998
  • 69
  • 209
  • 339
  • 2
    an instance initializer is not the same as an anonymous code block in a method. – assylias Aug 15 '12 at 14:24
  • 1
    Why?Does the OP ask specifically about methods?I thought that it asked about various uses of "silly" `{}` – Cratylus Aug 15 '12 at 14:26
  • There is `someCode` before the opening brace and `everythingElse` after the closing brace, so it seems to exclude instance initializers. But admittedly it is not 100% clear. – assylias Aug 15 '12 at 14:28
  • `someCode` could even be `static` from what I understand and so the OP is about `static initializers`. Also `private int myVar` is also `someCode`.But who knows right? ;) – Cratylus Aug 15 '12 at 14:31
  • Both static blocks and instance intializers are (somewhat) normal parts of the language, and both serve useful purposes. The OP is clearly asking about the fact that curly braces can be dropped in arbitrarily, and whether that actually serves any purpose. – dimo414 Aug 15 '12 at 14:34
  • You'd be surprised how many people don't understand what's going on when they see an instance initializer :) – Matt Aug 15 '12 at 15:26
0

If you named your codeblock you can break the block by adressing the name.

name1 : {
    name2 :{
        final int  i = 1;
        if( i == 1) {
            break name1;
        }
        System.out.println("name2");
    }
    System.out.println("name1");
}

You are also able to limit the scope of a variable, so after the end of the block the variable can easily gargabe-collected.

Simulant
  • 19,190
  • 8
  • 63
  • 98
0

It also lets you add labels so you can make spaghetti code!

MY_LABEL: {
  if (condition) {
    break MY_LABEL;
  }
  System.out.println("IN BLOCK");
}
System.out.println("OUTSIDE BLOCK");

If condition is true then the control flow will skip right over the first print statement and you'll only get the second print.

Disclaimer: I don't recommend using spaghetti code—this is only a hypothetical discussion of what you could do with a block like that.

DaoWen
  • 32,589
  • 6
  • 74
  • 101
  • Even then, this isn't how 'spaghetti code' is often understood. The 'goto' semantics in Java are fairly constrained (that is, it's understood it's solely a block early-exit control). `GOTO`s in languages like BASIC are horrendous, because you can go to _any_ line in the program (pretty much) - which can lead to some mind-bending code. Of course, if you're doing something like this in Java, you probably want to stick it in it's own method, so you actually exit the entire method early. – Clockwork-Muse Aug 15 '12 at 15:02
0

another use case: declaring final variables for anonymous subclasses. Obviously, you can't just reference "foo" in the anonymous subclass below. You'd have to make it "final". As an alternate, we copy the value into a new final variable and use that. The new variable is a snapshot value of "foo" as of the that particular point of time during the execution.

int foo = 1;

....

{
  final int bar = foo;
  Future<Void> future = executorService.submit(new Callable<Void>() { // use bar here });
}

I realize you could do this without the braces, but this limits the scope of the new variable.

Matt
  • 11,523
  • 2
  • 23
  • 33