Guide | Java

How to Throw Exceptions in Java

How to Throw Exceptions in Java

Throwing Exceptions in Java

When your application encounters invalid user input—say, an email address without an @ symbol or a password that's too short—how does it communicate this problem to the caller? Through exceptions.

Understanding how to throw exceptions in Java allows you to create higher quality code where errors are checked at compile time instead of runtime. It also enables you to design custom exceptions that make debugging and recovery easier.

Let's start with the basics of throwing exceptions then work our way up to when and how to create your own.

How to Throw Exceptions in Java

Throwing an exception is as simple as using the "throw" statement. You then specify the Exception object you wish to throw. Every Exception includes a message which is a human-readable error description. It's often related to problems with user input, server, backend, etc. Here's an example that shows how to throw an exception:

throw new Exception("Exception message");

You place this inside a method when you detect something wrong. For instance, if validating user input fails or a required resource is missing, you throw an exception to stop execution and notify the calling code that something needs attention. Like this:


public void processAge(int age) {
    if (age < 0) {
        throw new Exception("Age cannot be negative");
    }
    // rest of method continues if no exception thrown
}

When you throw an exception in a method like we just did, how does the calling code know to expect it? That's where the throws keyword comes in.

Using the Throws keyword

Throws is a keyword used to indicate that this method could throw this type of exception. The caller has to handle the exception using a try-catch block or propagate the exception. We can throw either checked or unchecked exceptions.

The throws keyword allows the compiler to help you write code that handles this type of error, but it does not prevent the abnormal termination of the program. With the help of the throws keyword, we can provide information to the caller of the method about the types of exceptions the method might throw.

type method_name(parameters) throws exception_list

In the above syntax, exception_list is a comma-separated list of all the exceptions a method might throw. For example:

void testMethod() throws ArithmeticException, ArrayIndexOutOfBoundsException {
    // rest of code
}

Here's a realistic example: validating user input. If a user provides an invalid age (negative or over 150), the method throws an exception to alert the caller:

static void validateAge(int age) throws IllegalArgumentException {
    if (age < 0 || age > 150) {
        throw new IllegalArgumentException("Invalid age: " + age);
    }
    // proceed with valid age
}

This must be handled with a try/catch block:

public class Example {
    public static void main(String[] arg) {
        try {
            validateAge(-5);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
    }
}

Types of exceptions

There are two types of exceptions in Java: checked (compile time) exceptions and unchecked (runtime) exceptions. For clarity, we’ll also discuss how errors are different than exceptions in Java.

Checked exception (compile time exception)

Checked exceptions must be caught and handled during compile time. If the compiler does not see a try or catch block or throws keyword to handle a checked exception, it throws a compilation error. Checked exceptions are generally caused by faults outside code like missing files, invalid class names, and networking errors.

FileInputStream fis = null;
try {
    fis = new FileInputStream("B:/myfile.txt");
} catch (FileNotFoundException e) {
    e.printStackTrace();
    rollbar.error(e, "Hello, Rollbar");
}

Unchecked exception (runtime exception)

Unchecked exceptions do not need to be explicitly handled; they occur at the time of execution, also known as run time. These exceptions can usually be avoided by good coding practices. They are typically caused by programming bugs, such as logic errors or improper use of APIs. These exceptions are ignored at the time of compilation. For example:

public class Main {
    public static void main(String[] args) {
        int a = 10, b = 0;
        System.out.println(a/b);      
    }
}

The example above will cause an ArithmeticException at the time of program execution, since a number can’t be divided by 0. It would throw an unhandled exception and the program would end.

What's the Difference Between an Exception and an Error?

People often refer to "errors" and “exceptions” as the same thing colloquially. However, in Java these are separate concepts. Errors are thrown by the Java Virtual Machine and cannot be caught or handled. They derive from java.lang.Error and they occur because of some fault in the environment in which the application is running. For example, stack overflows and out of memory exceptions are environment errors that result in the application exiting.

The Exception class

Before we get into creating custom exceptions, it helps to understand the foundation they're all built on: the Exception class.

The Exception class is the superclass of all recoverable exceptions in Java. When you create your own exception, you'll be extending this class, so let's see what it provides.

package java.lang;
public class Exception extends Throwable {
    static final long serialVersionUID = -3387516993124229948L;

    public Exception() {
        super();
    }

    public Exception(String message) {
        super(message);
    }

    public Exception(String message, Throwable cause) {
        super(message, cause);
    }

    public Exception(Throwable cause) {
        super(cause);
    }

    protected Exception(String message, Throwable cause, boolean enableSuppression, boolean     writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

The Exception class extends Throwable. The constructor contains two parameters: message and cause. The detailMessage parameter gives the details of the message for this exception, and the throwable parameter gives the cause of this exception.

The key takeaway: every exception needs a message explaining what went wrong, and optionally a cause pointing to the underlying exception that triggered it.

Custom Exceptions

Java’s built-in exceptions don’t always provide the information we need. So, we sometimes need to supplement these exceptions with our own. During some specific operation, if an exception occurs in your application, you need to recover and make the user know about it. A custom exception gives you more control to provide extra data about the problem and to handle the exception in your code.

The best practice is to extend the java.lang.Exception class with a new class, following the general naming convention as provided by the JDK (Java Development Kit). The new class requires a constructor that will take a string as the error message—it is called the parent class constructor.

public class HandledException extends Exception {
    private String code;

    public HandledException(String code, String message) {
        super(message);
        this.setCode(code);
    }

    public HandledException(String code, String message, Throwable cause) {
        super(message, cause);
        this.setCode(code);
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }
}

For example, let’s say a program fails to connect to a database. You could use a custom exception to collect information like the database URL, username, password, etc. In the catch block, you could write this information to the log and display a basic message to the user like "failed to connect to database."

public class MainClass {

    private static String DATABASE_EXCEPTION = "DATABASE_EXCEPTION";
    private static final Logger logger = Logger.getLogger(MainClass.class);

    public static void main(String[] args) {
        try {
            makeDatabaseConnection();
        } catch (HandledException e) {
            rollbar.error(e, "Hello, Rollbar");
            // Display custom message to the user
            System.out.println("Code: "+e.getCode()+” Exception Message : ”+e.getMessage());
            // Log the exception detail
            logger.error("Exception: ", e);
        }
    }

    static void makeDatabaseConnection() throws HandledException {
        String dbURL = "jdbc:sqlserver://localhost\sqlexpress";
        String userName = "sa";
        String password = "secret";
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(dbURL, userName, password);
        } catch (SQLException e) {
            rollbar.error(e, "Hello, Rollbar");
            throw new HandledException(DATABASE_EXCEPTION,"Failed to connect to database", e);
        }
    }
}

You now have the tools to throw, declare, and create custom exceptions in your Java applications. But once your code is running in production, how do you track and manage them all?

Track and Manage Exceptions in Production with Rollbar

Managing errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Rollbar can help throw Java exceptions as well as track, analyze, and manage errors in real-time to help you to proceed with more confidence. Try it today!

Related Resources