Search code examples
javajls

Why do try/catch or synchronized in Java require a statement block?


Java allows for certain keywords to be followed by a statement or a statement block. For example:

if (true)
    System.out.println("true");

do
    System.out.println("true");
while (true);

compiles as well as

if(true) {
    System.out.println("true");
}

do {
   System.out.println("true");
} while (true);

This is also true for keywords like for, while etc.

However, some keywords don't allow this. synchronized requires a block statement. Same for try ... catch ... finally, which requires at least two block statements following the keywords. For example:

try {
    System.out.println("try");
} finally {
    System.out.println("finally");
}

synchronized(this) {
    System.out.println("synchronized");
}

works, but the following doesn't compile:

try
    System.out.println("try");
finally
    System.out.println("finally");

synchronized (this)
    System.out.println("synchronized");

So why do some keywords in Java require a block statement, while others allow a block statement as well as a single statement? Is this an inconsistency in language design, or is there a certain reason for this?


Solution

  • You get a dangling else-like ambiguity if you try to allow leaving out the braces. Whilst this could be solved in a similar fashion to the dangling-else, probably best not to.

    Consider

    try
    try 
    fn();
    catch (GException exc)
    g();
    catch (HException exc)
    h();
    catch (IException exc)
    i();
    

    Does that mean

    try
        try 
            fn();
        catch (GException exc)
            g();
        catch (HException exc)
            h();
    catch (IException exc)
        i();
    

    or

    try
        try 
            fn();
        catch (GException exc)
            g();
    catch (HException exc)
        h();
    catch (IException exc)
        i();
    

    I believe in CLU, catch blocks were around just one statement (may be wrong).