I didn't know methods could have floating blocks like this:开发者_如何转开发
class X {
public static void main( String [] args ) {
{ //<--- start
int i;
} //<-- ends
}
}
I was aware of floating blocks outside methods, but never tried them inside.
This could probably be used to define local scope or something.
Is there a use for floating blocks inside methods in Java?
Is there a use?
Yes - to limit the scope of local variables.
Is it a good idea?
Probably debatable (and likely will be).
The "pro" camp will say it never hurts to narrow the scope of variable. The "con" camp will say that, if you use it in a method and your method is long enough to warrant narrowing the scope of variables to specific sections, then it is probably an indication that you should make separate methods out of the different sections.
Personally, I use them, e.g.:
public void doGet(
final HttpServletRequest request,
final HttpServletResponse response)
throws IOException {
final PersistenceManager pm = PMF.get().getPersistenceManager();
final List<ToDoListGaejdo> toDoLists;
{
final Query query = pm.newQuery(ToDoListGaejdo.class);
query.setOrdering("listName asc");
toDoLists = (List<ToDoListGaejdo>) query.execute();
}
final List<ToDoItemGaejdo> entries;
{
final Query query = pm.newQuery(ToDoItemGaejdo.class);
query.setOrdering("listName asc, priority asc");
entries = (List<ToDoItemGaejdo>) query.execute();
}
final ServletOutputStream out = response.getOutputStream();
out.println("<head>");
out.println(" <title>Debug View</title>");
....
Yes, they are useful for two purposes.
First, you can limit the scope of variables using such blocks. This can help with the readability of code, because you have a smaller area to consider when determining how a variable is used. Additionally, this can minimize the required number of "slots" for the method frame, conserving stack space. I'd be very surprised to find a case where this optimization was necessary.
Second, when you attach a label to the block, a targeted break
can be used inside the block to jump to the end of the block. This is not quite as evil as an unadulterated goto
statement, but a sighting still triggers red flags and warning bells.
You've just given an example yourself. You can make the declaration of i 'more local' than method scope. When it goes out of scope, the rest of the method can't see it.
Syntactically, a block can appear anywhere a statement can appear. This is the fundamental principle of block-structured languages.
One further case where blocks are useful is in switch
statements; e.g. the following is invalid
switch (i) {
case 1:
float j = ...;
break;
case 2:
float j = ...; // compilation error
break;
...
}
but it is OK with added blocks:
switch (i) {
case 1:
{
float j = ...;
break;
}
case 2:
{
float j = ...; // just fine
break;
}
...
}
This kind of use-case arises when you implement things like state machines and interpreters using (big) switch statements. You could argue that the local variables should all have different names, but:
- using the same name for the same concept (though in a different scope) in gnarly code like this is good for large-scale readability, and
- using the blocks makes it easier for the compilers to recognize that the variables declared within may share stack frame slots. This is potentially significant if the enclosing method is also recursive.
(OK, this is all either micro-optimization, or a consequence of micro-optimization. But let's assume we've determined that it is justified.)
精彩评论