javasemantics

'not a statement' in Java


I suppose this is more a question about language theory than anything else. Why is the first statement in main legal, when the second is not? Don't they evaluate to be the same thing?

public class Main {
        public static void main(String[] args) {
                foo();
                0;
        }
        public static int foo(){
                return 0;
        }
}

Solution

  • Java restricts the types of expressions that are allowed in so-called "expression statements". Only meaningful expressions that have potential side effects are allowed. It disallows semantically meaningless statements like 0; or a + b;. They're simply excluded from the language grammar.

    A function call like foo() can, and usually does, have side effects, so it is not a meaningless statement. The compiler doesn't deeply inspect the body of foo() to check whether it actually does anything. Calling a function can have side effects, so it is syntactically valid.

    This reflects a philosophical difference between C/C++ and Java. Java prohibits various constructs which result in dead or meaningless code.

    return;
    foo();    // unreachable statement
    

    C and C++ are relatively laissez faire about it all. Write whatever you want; they don't have time to babysit you.


    Quoting from the Java Language Specification, §14.8 Expression Statements:

    Certain kinds of expressions may be used as statements by following them with semicolons.

    ExpressionStatement:
        StatementExpression ;
    
    StatementExpression:
        Assignment
        PreIncrementExpression
        PreDecrementExpression
        PostIncrementExpression
        PostDecrementExpression
        MethodInvocation
        ClassInstanceCreationExpression
    

    An expression statement is executed by evaluating the expression; if the expression has a value, the value is discarded.

    Execution of the expression statement completes normally if and only if evaluation of the expression completes normally.

    Unlike C and C++, the Java programming language allows only certain forms of expressions to be used as expression statements. Note that the Java programming language does not allow a "cast to void" - void is not a type - so the traditional C trick of writing an expression statement such as:

    (void)... ;  // incorrect!
    

    does not work. On the other hand, the Java programming language allows all the most useful kinds of expressions in expressions statements, and it does not require a method invocation used as an expression statement to invoke a void method, so such a trick is almost never needed. If a trick is needed, either an assignment statement (§15.26) or a local variable declaration statement (§14.4) can be used instead.