Throw & Throws

Java Exception Handling: Throw and Throws

Throw

Sometimes we can create exception objects explicitly and hand them over to the JVM manually. For this, we have to use the throw keyword. Thus, the main objective of the throw keyword is to hand over our created exception object to the JVM manually.

throw new ArithmeticException("division by zero");

Hence, the result of the following two programs is the same.

JVM creates exception object Programmer creates exception object
class Test {
    public static void main(String[] args) {
        System.out.print(10/0);
    }
}

Output:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Test.main(Test.java:4)

In this case, the main method is responsible for creating the exception object and handing it over to the JVM.

class Test {
    public static void main(String[] args) {
        throw new ArithmeticException("/ by zero");
    }
}

Output:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Test.main(Test.java:4)

In this case, the programmer creates the exception object explicitly and hands it over to the JVM manually.

Note:

The best use of the throw keyword is for user-defined or customized exceptions.

Case 1:

throw e; if e refers to null, then we will get a NullPointerException.

Valid exception object Null exception object
class Test {
    static ArithmeticException e = new ArithmeticException();
    public static void main(String[] args) {
        throw e;
    }
}
class Test {
    static ArithmeticException e;
    public static void main(String[] args) {
        throw e;
    }
}

Output:

NullPointerException

Case 2:

We are not allowed to write any statement directly after throw; otherwise, we will get a compile-time error saying "unreachable statement."

Runtime Exception (allowed) Throw with unreachable statement (error)
class Test {
    public static void main(String[] args) {
        System.out.print(10/0);
        System.out.print("Hello");
    }
}

Runtime Exception

class Test {
    public static void main(String[] args) {
        throw new ArithmeticException("/ by zero");
        System.out.print("Hello");
    }
}

Compile Time Error: unreachable statement

Case 3:

We can use the throw keyword only for Throwable types. If we try to use it for normal Java objects, we will get a compile-time error.

Invalid (not Throwable) Valid (extends RuntimeException)
class Test {
    public static void main(String[] args) {
        throw new Test();
    }
}

Compile Time Error:

Test.java:4: error: incompatible types: Test cannot be converted to Throwable
    throw new Test();
    ^
1 error
class Test extends RuntimeException {
    public static void main(String[] args) {
        throw new Test();
    }
}

Output:

Exception in thread "main" Test
    at Test.main(Test.java:4)

Throws

In our program, if there is a possibility of raising a checked exception, we must handle the checked exception; otherwise, we will get a compile-time error saying "unreported exception XXX must be caught or declared to be thrown."

Example 1:

import java.io.*;
class Test {
    public static void main(String[] args) {
        PrintWriter pw = new PrintWriter("abc.txt");
        pw.println("Hello");
    }
}

Compile time error: unreported exception java.io.FileNotFoundException must be caught or declared to be thrown.

Example 2:

class Test {
    public static void main(String[] args) {
        Thread.sleep(1000);
    }
}

Compile time error: unreported exception java.lang.InterruptedException must be caught or declared to be thrown.

We can handle this compile-time error by using the following two ways:

  1. try-catch:
    class Test {
        public static void main(String[] args) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
        }
    }
  2. throws: We can use the throws keyword to delegate responsibility of exception handling to the caller (it may be another method or JVM). Then the caller method is responsible to handle that exception.
    class Test {
        public static void main(String[] args) throws InterruptedException {
            Thread.sleep(1000);
        }
    }

Points:

  • The throws keyword is required only for checked exceptions. Usage of the throws keyword for unchecked exceptions has no use or impact.
  • The throws keyword is required only to convince the compiler. Usage of the throws keyword does not prevent abnormal termination of the program.
    class HelloWorld {
        public static void main(String args[]) throws InterruptedException {
            dco();
        }
        public static void dco() throws InterruptedException {
            doo();
        }
        public static void doo() throws InterruptedException {
            dooo();
        }
        public static void dooo() throws InterruptedException {
            Thread.sleep(1000);
        }
    }

    In the above program, at least one throws keyword is needed; otherwise, the code won't compile.

Conclusion of throws keyword:

  • We can use it to delegate responsibility of exception handling to the caller (it may be a method or JVM).
  • It is required only for checked exceptions and has no impact for unchecked exceptions.
  • It is required only to convince the compiler and does not prevent abnormal termination of the program.

Note:

It is recommended to use try-catch over the throws keyword.

Case 1:

We can use the throws keyword for methods and constructors but not for classes.

class HelloWorld {
    HelloWorld() throws Exception {
    }
    public static void DO() throws Exception {
    }
    public static void main(String args[]) {
    }
}

Case 2:

We can use the throws keyword only for Throwable types. If we try to use it for normal Java classes, we will get a compile-time error saying "incompatible types."

Invalid (not Throwable) Valid (Throwable)
class Test {
    public static void main(String[] args) throws Test {
        System.out.println("Hello, World!");
    }
}

incompatible types: Test cannot be converted to Throwable

class Test extends RuntimeException {
    public static void main(String[] args) throws Test {
        System.out.println("Hello, World!");
    }
}

Case 3:

Checked Exception (requires handling) Error (no handling required)
class Test {
    public static void main(String[] args) {
        throw new Exception();
    }
}

CE: unreported exception Exception; must be caught or declared to be thrown

class Test {
    public static void main(String[] args) {
        throw new Error();
    }
}

RE:

Exception in thread "main" java.lang.Error

Case 4:

Within the try block, if there is no chance of raising an exception, we can't write a catch block for that exception; otherwise, we will get a compile-time error saying "Exception XXX never thrown in body of corresponding try statement." But this rule is applicable for fully checked exceptions.

Unchecked Exception (allowed) Checked Exception (not allowed)
class HelloWorld {
    public static void main(String[] args) {
        try {
            System.out.print("Hello");
        } catch (ArithmeticException e) {
        }
    }
}
import java.io.*;
class HelloWorld {
    public static void main(String[] args) {
        try {
            System.out.print("Hello");
        } catch (IOException e) {
        }
    }
}

error: exception IOException is never thrown in body of corresponding try statement

class HelloWorld {
    public static void main(String[] args) {
        try {
            System.out.print("Hello");
        } catch (Exception e) {
        }
    }
}
class HelloWorld {
    public static void main(String[] args) {
        try {
            System.out.print("Hello");
        } catch (InterruptedException e) {
        }
    }
}

error: exception InterruptedException is never thrown in body of corresponding try statement

class HelloWorld {
    public static void main(String[] args) {
        try {
            System.out.print("Hello");
        } catch (Error e) {
        }
    }
}

0 Comments