Exceptions
An exception is an error-caused event that disrupts the normal flow of a program. It can be handled to maintain program stability.
If we want to prevent errors, we can use the try
and catch
blocks. If inside the try
block, an exception is thrown (an exception is returned through the throw
statement) or it occurs unforeseen (e.g., the user divides by 0), the rest of the instructions inside this block are skipped, and the catch
block for a given exception type executes (it will catch this exception). If inside of catch
, instead of the specific exception type the catch
block is supposed to look for (e.g., ArithmeticException
), we type Exception
, it will execute for the exception types that don't have their own specified catch
block. We can add a third block - finally
. It executes at the end regardless of what happens in try
or catch
. It is usually used to perform close-up actions, like closing files or connections.
We can trigger a specific type of error by "throwing" an exception (throw new...
). This can be used, e.g., inside the try
block, to invoke a specific exception, but also outside of try-catch to deliberately stop program execution when a critical error occurs. A common use case is validating user input when the provided data does not meet the required format.
In the example below, the division()
function throws an exception of a DivisionException
type (our class's type) when someone tries to divide by zero. This exception will be caught, and the getErrorMessage()
method from our class will be called (it will display an error message). Creating our own exceptions can be useful when we want to handle specific error conditions in a more meaningful and organized way, allowing us to attach custom messages and methods.
public class Main {
static double division(double x, double y) throws DivisionException { // "throws" says what exception this function may (but doesn't have to) return
if (y == 0) {
throw new DivisionException("Don't divide by 0!");
}
return x / y;
}
public static void main(String[] args) {
int x = 10;
try {
if (x == 10) {
throw new Exception("x equals 10");
}
System.out.println("x");
}
catch (Exception e) {
System.out.println("General exception: " + e.getMessage()); // e.getMessage() provides the error description
}
finally {
System.out.println("I am executed regardless of anything.");
}
System.out.println();
try {
double result = division(5, 0);
}
catch (DivisionException e) {
e.getErrorMessage();
}
}
}
class DivisionException extends Exception {
public DivisionException(String string) {
super(string);
}
public void getErrorMessage() {
System.out.println("Don't divide by 0!");
}
}
Error examples
- An
ArrayIndexOutOfBoundsException
occurs when we try to access an index outside the bounds of an array. - A
NullPointerException
occurs when we try to access a method or field on a null reference. - A
ClassCastException
occurs when we try to cast an object to a subclass it is not an instance of. - An
IllegalArgumentException
occurs when a method receives an argument that is inappropriate or invalid. - An
ArithmeticException
occurs when we attempt an illegal arithmetic operation, such as division by zero. - A
NumberFormatException
occurs when we try to convert a string to a number but the string does not have the correct format.
The assert
keyword
The assert
keyword checks whether a given condition is true, and if not, throws an AssertionError
with a user-written comment. To enable assertions, the -ea
(or -enableassertions
) JVM option must be used when running the program. A common use case is debugging complex functions by asserting that input values or intermediate results meet expected conditions before continuing execution.
int number = -5;
assert number > 0 : "The number must be positive.";
System.out.println("Number is: " + number);