Tuesday, 22 April 2008

Statements Chapter in JLS 3rd Edition

Today i was going through chapter "Blocks And Statements" in JLS Specification and wanted to share few important key notes found in this chapter.

1) Section 14.3 Local Class Declarations states that

It is a compile-time error if a local class declaration contains any one of the following access modifiers: public, protected, private, or static.


public void test() {
private class A {

}
}


2) In Section 14.4.2 Scope of Local Variable Declarations it states

A local variable cannot be referred to using a qualified name (§6.6), only a simple name.


class Test {
static int x;
public static void main(String[] args) {
int x = x;
}
}


causes a compile-time error because the initialization of x is within the scope of the declaration of x as a local variable, and the local x does not yet have a value and cannot be used.

The following program does compile:


class Test {
static int x;
public static void main(String[] args) {
int x = (x=2)*2;
System.out.println(x);
}
}


3) 14.10 The assert Statement section states

There is one case that demands special treatment. Recall that the assertion status of a class is set at the time it is initialized. It is possible, though generally not desirable, to execute methods or constructors prior to initialization. This can happen when a class hierarchy contains a circularity in its static initialization, as in the following example:


public class Foo {
public static void main(String[] args) {
Baz.testAsserts();
// Will execute after Baz is initialized.
}
}
class Bar {
static {
Baz.testAsserts();
// Will execute before Baz is initialized!
}
}
class Baz extends Bar {
static void testAsserts(){
boolean enabled = false;
assert enabled = true;
System.out.println("Asserts " +
(enabled ? "enabled" : "disabled"));
}
}


Invoking Baz.testAsserts() causes Baz to get initialized. Before this can happen, Bar must get initialized. Bar's static initializer again invokes Baz.testAsserts(). Because initialization of Baz is already in progress by the current thread, the second invocation executes immediately, though Baz is not initialized (JLS 12.4.2).

If an assert statement executes before its class is initialized, as in the above example, the execution must behave as if assertions were enabled in the class.

In other words, if the program above is executed without enabling assertions, it must print:

Asserts enabled
Asserts disabled

4) Section 14.20.1 Execution of try-catch states that

A try statement without a finally block is executed by first executing the try block. Then there is a choice:

If execution of the try block completes normally, then no further action is taken and the try statement completes normally.

If execution of the try block completes abruptly because of a throw of a value V, then there is a choice:

If the run-time type of V is assignable (§5.2) to the Parameter of any catch clause of the try statement, then the first (leftmost) such catch clause is selected. The value V is assigned to the parameter of the selected catch clause, and the Block of that catch clause is executed. If that block completes normally, then the try statement completes normally; if that block completes abruptly for any reason, then the try statement completes abruptly for the same reason.

If the run-time type of V is not assignable to the parameter of any catch clause of the try statement, then the try statement completes abruptly because of a throw of the value V.

If execution of the try block completes abruptly for any other reason, then the try statement completes abruptly for the same reason


class BlewIt extends Exception {
BlewIt() { }
BlewIt(String s) { super(s); }
}
class Test {
static void blowUp() throws BlewIt { throw new BlewIt(); }
public static void main(String[] args) {
try {
blowUp();
} catch (RuntimeException r) {
System.out.println("RuntimeException:" + r);
} catch (BlewIt b) {
System.out.println("BlewIt");
}
}
}


the exception BlewIt is thrown by the method blowUp. The try-catch statement in the body of main has two catch clauses. The run-time type of the exception is BlewIt which is not assignable to a variable of type RuntimeException, but is assignable to a variable of type BlewIt, so the output of the example is:

BlewIt

5) Section 14.20.2 Execution of try-catch-finally states that

A try statement with a finally block is executed by first executing the try block. Then there is a choice:

If the run-time type of V is not assignable to the parameter of any catch clause of the try statement, then the finally block is executed. Then there is a choice:

If the finally block completes normally, then the try statement completes abruptly because of a throw of the value V.

If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and the throw of value V is discarded and forgotten).


class BlewIt extends Exception {
BlewIt() { }
BlewIt(String s) { super(s); }
}
class Test {
static void blowUp() throws BlewIt {
throw new NullPointerException();
}
public static void main(String[] args) {
try {
blowUp();
} catch (BlewIt b) {
System.out.println("BlewIt");
} finally {
System.out.println("Uncaught Exception");
}
}
}


Hope this helps if any.

No comments: