Next Prev Up Contents

## 8 Statements

8.1 - Declarations
8.2 - Expressions
8.3 - Control Flow
8.4 - Exceptions
8.4.1 - The finally Statement
8.4.2 - Runtime Exceptions

### 8.1 Declarations

Declarations can appear anywhere that a statement is allowed. The scope of the declaration ends at the end of the enclosing block.

In addition, declarations are allowed at the head of for statements, as shown below:

        for (int i = 0; i < 10; i++) {
            ...
        }

Items declared in this way are valid only within the scope of the for statement. For example, the preceding code sample is equivalent to the following:

        {
            int i = 0;
            for (; i < 10; i++) {
            ...
            }
        }

### 8.2 Expressions

Expressions are statements:

        a = 3;
        print(23);
        foo.bar();

### 8.3 Control Flow

The following is a summary of control flow:

    if(boolean) statement
    else statement
    switch(e1) {
    	case e2: statements
    	default: statements
    }
    break [label];
    continue [label];
    return e1;
    for([e1]; [e2]; [e3]) statement
    while(boolean) statement
    do statement while(boolean);
    label:statement

The language supports labeled loops and labeled breaks, for example:

        outer:   // the label
            for (int i = 0; i < 10; i++) {
                for (int j= 0; j< 10; j++) {
                    if (...) {
                        break outer;
                    }
                    if (...) {
                    }
                }
        }

The use of labels in loops and breaks has the following rules:

- Any statement can have a label.

- If a break statement has a label it must be the label of an enclosing statement.

- If a continue statement has a label it must be the label of an enclosing loop.

### 8.4 Exceptions

When an error occurs in an Java program--for example, when an argument has an invalid value--the code that detects the error can throw an exception*1. By default, exceptions result in the thread terminating after printing an error message. However, programs can have exception handlers that catch the exception and recover from the error.

Some exceptions are thrown by the Java runtime system. However, any class can define its own exceptions and cause them to occur using throw statements. A throw statement consists of the throw keyword followed by an object. By convention, the object should be an instance of Exception or one of its subclasses. The throw statement causes execution to switch to the appropriate exception handler. When a throw statement is executed, any code following it is not executed, and no value is returned by its enclosing method. The following example shows how to create a subclass of Exception and throw an exception.

        class MyException extends Exception {
        }

        class MyClass {
            void oops() {
                if (/* no error occurred */) {
                    ...
                } else { /* error occurred */
                throw new MyException();
                }
            }
        }

To define an exception handler, the program must first surround the code that can cause the exception with a try statement. After the try statement come one or more catch statements--one per exception class that the program can handle at that point. In each catch statement is exception handling code. For example:

        try {
            p.a = 10;
        } catch (NullPointerException e) {
            println("p was null");
        } catch (Exception e) {
            println("other error occurred");
        } catch (Object obj) {
            println("Who threw that object?");
        }

A catch statement is like a method definition with exactly one parameter and no return type. The parameter can be either a class or an interface. When an exception occurs, the nested try/catch statements are searched for a parameter that matches the exception class. The parameter is said to match the exception if it:

- is the same class as the exception; or

- is a superclass of the exception; or

- if the parameter is an interface, the exception class implements the interface.

The first try/catch statement that has a parameter that matches the exception has its catch statement executed. After the catch statement executes, execution resumes after the try/catch statement. It is not possible for an exception handler to resume execution at the point that the exception occurred. For example, this code fragment:

        print("now ");
        try {
            print("is ");
            throw new MyException();
            print("a ");
        } catch(MyException e) {
            print("the ");
        }
        print("time\n");

prints "now is the time". As this example shows, exceptions don't have to be used only for error handling, but any other use is likely to result in code that's hard to understand.

Exception handlers can be nested, allowing exception handling to happen in more than one place. Nested exception handling is often used when the first handler can't recover completely from the error, yet needs to execute some cleanup code (as shown in the following code example). To pass exception handling up to the next higher handler, use the throw keyword using the same object that was caught. Note that the method that rethrows the exception stops executing after the throw statement; it never returns.

        try {
            f.open();
        } catch(Exception e) {
            f.close();
            throw e;
        }

#### 8.4.1 The finally Statement

The following example shows the use of a finally statement that is useful for guaranteeing that some code gets executed whether or not an exception occurs. For example, the following code example:

        try {
            // do something
        } finally {
            // clean up after it
        }

is similar to:

        try {
            // do something
        } catch(Object e){
            // clean up after it
            throw e;
        }
        // clean up after it

The finally statement is executed even if the try block contains a return, break, continue, or throw statement. For example, the following code example always results in "finally" being printed, but "after try" is printed only if a != 10.

        try {
            if (a == 10) {
                return;
            }
        } finally {
            print("finally\n");
        }
        print("after try\n");

#### 8.4.2 Runtime Exceptions

This section contains a list of the exceptions that the Java runtime throws when it encounters various errors.

ArithmeticException

Attempting to divide an integer by zero or take a modulus by zero throw the ArithmeticException--no other arithmetic operation in Java throws an exception. For information on how Java handles other arithmetic errors see Operators on Integers and Operators on Floating Point Values.

For example, the following code causes an ArithmeticException to be thrown:

        class Arith {
            public static void main(String args[]) {
                int j = 0;
                j = j / j;
            }
        }

NullPointerException

An attempt to access a variable or method in a null object or a element in a null array throws a NullPointerException. For example, the accesses o.length and a[0] in the following class declaration throws a NullPointerException at runtime.

        class Null {
            public static void main(String args[]) {
                String o = null;
                int a[] = null;
                o.length();
                a[0] = 0;
            }
        }

It is interesting to note that if you throw a null object you actually throw a NullPointerException.

IncompatibleClassChangeException

In general the IncompatibleClassChangeException is thrown whenever one class's definition changes but other classes that reference the first class aren't recompiled. Four specific changes that throw a IncompatibleClassChangeException at rutime are:

- A variable's declaration is changed from static to non-static in one class but other classes that access the changed variable aren't recompiled.

- A variable's declaration is changed from non-static to static in one class but other classes that access the changed variable aren't recompiled.

- A field that is declared in one class is deleted but other classes that access the field aren't recompiled.

- A method that is declared in one class is deleted but other classes that access the method aren't recompiled.

ClassCastException

A ClassCastException is thrown if an attempt is made to cast an object O into a class C and O is neither C nor a subclass of C. For more information on casting see Casting Between Class Types.

The following class declaration results in a ClassCastException at runtime:

        class ClassCast {
            public static void main(String args[]) {
                Object o = new Object();
                String s = (String)o;           // the cast attempt
                s.length();
            }
        }

NegativeArraySizeException

A NegativeArraySizeException is thrown if an array is created with a negative size. For example, the following class definition throws a NegativeArraySizeException at runtime:

        class NegArray {
            public static void main(String args[]) {
                int a[] = new int[-1];
                a[0] = 0;
            }
        }

OutOfMemoryException

An OutOfMemoryException is thrown when the system can no longer suppy the application with memory. The OutOfMemoryException can only occur during the creation of an object, i.e., when new is called. For example, the following code results in an OutOfMemoryException at runtime:

        class Link {
            int a[] = new int[1000000];
            Link l;
        }
        class OutOfMem {
            public static void main(String args[]) {
                Link root = new Link();
                Link cur = root;
                while(true) {
                    cur.l = new Link();
                    cur = cur.l;
                }
            }
        }

NoClassDefFoundException

A NoClassDefFoundException is thrown if a class is referenced but the runtime system cannot find the referenced class.

For example, class NoClass is declared:

        class NoClass {
            public static void main(String args[]) {
                C c = new C();
            }
        }

When NoClass is run, if the runtime system can't find C.class it throws the NoClassDefFoundException.

C.class must have existed at the time NoClass is compiled.

IncompatibleTypeException

An IncompatibleTypeException is thrown if an attempt is made to instantiate an interface. For example, the following code causes an IncompatibleTypeException to be thrown.

        interface I {
        }

        class IncompType {
            public static void main(String args[]) {
                I r = (I)new("I");
            }
        }

ArrayIndexOutOfBoundsException

An attempt to access an invalid element in an array throws an ArrayIndexOutOfBoundsException. For example:

        class ArrayOut {
            public static void main(String args[]) {
                int a[] = new int[0];
                a[0] = 0;
            }
        }

UnsatisfiedLinkException

An UnsatisfiedLinkException is thrown if a method is declared native and the method cannot be linked to a routine in the runtime.

        class NoLink {
            static native void foo();

            public static void main(String args[]) {
                foo();
            }
        }

InternalException

An InternalException should never be thrown. It's only thrown if some consistency check in the runtime fails. Please send mail to
java@java.Sun.COM if you have a reproducible case that throws this exception.

Next Prev Up Contents

The Java Language Specification

Generated with CERN WebMaker