Using of standard Java exceptions simplifies the understanding of every project. But they are much exceptions that we can use and it's not always simple to found the right one.
In this article we'll focus on different types of exceptions in Java. To simplify the reading, we won't divide this article on different parts. Instead of it, all exceptions will be presented in two tables : one for unchecked exceptions and another one for checked exceptions. The difference between these two types is that ones are can be detected at conception time and the others only at runtime.
Exceptions detected at conception time are called checked ant they must be caught or thrown. They also can be predicted, for example: when we try to work with a non-existent file with FileInputStream, an FileNotFoundException can be thrown. This type of exceptions is declared at API level.
Unchecked exceptions are more difficult to predict and occur at runtime, for example because of unexpected input as the operations on null object while it was expected to be not null.
Types of checked exceptions
See checked exceptions in Java
Exception |
Explanation |
Sample |
ClassNotFoundException |
occurs when a class is not found (for exemple a class presents on compile time but not on runtime) |
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
public class NotFound{
public static void main(final String[] args){
try{
FileUtils.writeStringToFile(new File("./testFile.txt"), "testData");
}
catch(final IOException e){
e.printStackTrace();
}
}
}
After, compile and execute this class without specifying org.apache.commons in classpath :
java NotFound
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Logger
// ...
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Logger
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
... 5 more
|
CloneNotSupportedException |
is thrown when we attempt to clone a non-cloneable object (for example an object which doesn't implement Clonbeable interface) |
public class Test1{
public static void main(String[] args) {
Test1 t1 = new Test1();
t1.clone();
}
}
|
IllegalAccessException |
occurs when some method tries to access an inaccessible method or field. For example, can be launch when we try to invoke a class private method or constructor with API reflection. |
try{
Constructor c=PrivateConstructor.class.getDeclaredConstructor();
c.newInstance();
}
catch(IllegalAccessException ae){
e.printStackTrace();
}
catch(Exception ex){
ex.printStackTrace();
}
// other file
public class PrivateConstructor {
private PrivateConstructor() {
}
}
|
InstantiationException |
when we try to instantiate an object and the insantiation isn't make successfully, this exceptions will be launched. It can occur, for example, when we try to invoke an 0-arguments constructor which is undefined in the class. |
public class Test1 {
private Test1(int i) {
}
}
// ...
// failing code
Class<?> c=Class.forName("exception.Test1");
Object o=c.newInstance();
|
InterruptedException |
in multi-threading applications, when one thread interrupts the work of another, InterruptedException occurs. |
Thread mainThread=Thread.currentThread();
Thread interruptor=new Thread(new Runnable(){
@Override
public void run(){
System.out.println("Interruptor running !");
}
});
interruptor.start();
mainThread.interrupt();
try{
Thread.sleep(2000);
}
catch(InterruptedException e){
e.printStackTrace();
}
|
NoSuchFieldException |
thrown when the requested field doesn't exists |
try{
final Field field=String.class.getField("inexistendField");
}
catch(final NoSuchFieldException exc){
System.out.println("A NoSuchFieldException was caught "+exc.getMessage());
}
|
NoSuchMethodException |
thrown for non-existent method |
// we try to call String.inexistentStringMethod() method with API reflection
try{
final Method toInvoke=String.class.getDeclaredMethod("inexistentStringMethod");
final String result=(String)toInvoke.invoke(String.class);
System.out.println("Invoke testWithParam method. Get "+result+".");
}
catch(final NoSuchMethodException exc){
System.out.println("A NoSuchMethodException was caught "+exc.getMessage());
}
catch(final Exception e){
e.printStackTrace();
}
|
Unchecked exceptions
See unchecked exceptions in Java
Exception |
Explanation |
Sample |
ArithmeticException |
occurs when an arithmetic operation fails (for example: division by zero) |
int age = 27;
float average = age/0;
|
ArrayIndexOutOfBoundsException |
is thrown when index of demanded array doesn't exist |
String[] testArray=new String[] {"0"};
System.out.println("1 :"+testArray[1]);
|
ArrayStoreException |
this exceptions occurs when we try to store an inappropriate value in the array, for example, when we try to put an Integer's instance into String's array. This exceptions won't come out in compile time and it's the reason why it's so important to make only typesafe instances. |
Object[] stringArray=new String[3];
stringArray[0]="0 key";
stringArray[1]="1 key";
stringArray[2]=new Integer(3);
|
ClassCastException |
occurs when we try to cast an object into class that it doesn't support |
Object test="Sss";
List<String> testList=(List)test;
|
IllegalArgumentException |
argument used to invoke a method is incorrect |
Age age=new Age();
age.setAge(-1);
// ...
class Age{
private int age;
public void setAge(final int age) throws IllegalArgumentException {
if(age<0) throw new IllegalArgumentException("Age can't be a negatif number (passed age: "+age+")");
this.age=age;
}
public int getAge(){
return this.age;
}
}
|
IllegalMonitorStateException |
according to the Javadoc, it occurs when we use wait(), notify() and notifyAll() methods incorrectly. In other words, to invoke this method, we need to handle the locks on the objects concerned by these 3 methods. One of locks handling methods is the use of synchronized() block on notified or waiting object. This exception comes from multi-threading environment too. |
Thread t1=new Thread(new Runnable(){
@Override
public void run(){
while(true){
try{
wait();
}
catch(Exception e){
e.printStackTrace();
}
}
};
});
t1.notify();
|
IllegalStateException |
this exceptions depends on the object state. If we try to work if an object with has an inappropriate state to do its job, IllegalStateException should be thrown. For example, it could be a object which counts the words in one big plaintext file. But the counting can be done only when the file is fully loaded. Otherwise, an IllegalStateException is thrown. |
TextCounter counter=new TextCounter(new FileLoader());
counter.countWords();
// ...
class TextCounter{
private final FileLoader fileLoader;
public TextCounter(final FileLoader fileLoader){
this.fileLoader=fileLoader;
}
public void countWords() throws IllegalStateException{
if(!this.fileLoader.isLoaded()) throw new IllegalStateException("File must be fully loaded before word counting.");
}
}
class FileLoader{
private boolean isLoaded=false;
public void setToLoaded(){
this.isLoaded=true;
}
public boolean isLoaded(){
return this.isLoaded;
}
}
|
IllegalThreadStateException |
it's thrown every time where we try to make an operation on a thread with an inappropriate state. For example, it will be thrown when we'll attempt to start already started thread. |
Thread t1=new Thread();
t1.start();
t1.start();
|
IndexOutOfBoundsException |
looks like ArrayIndexOutOfBoundsExceptions, but is applied into collections like lists |
List<String> outArray=new ArrayList<String>();
System.out.println("First index is :"+outArray.get(1));
|
NegativeArraySizeException |
very rare exception produced when we try to initialize an array with negative value. The negative initialization can be made accidentally, for example after some of mathematical operations. Almost never it's set explicitly by programmer. |
int workers=3;
int jobs=10;
// Nota : we make a logical mistake by substracting workers number from jobs to get the number of not taken jobs... It can happen to
// everybody. It can happen ever more often when workers and jobs values are generated in dynamic strategy (database changing every 5
// minutes or something like that)
final int jobsToTake=workers-jobs;
final String[] jobsList=new String[jobsToTake];
|
NullPointerException |
thrown when we try to access to a method of null object |
String npeTest=null;
npeTest.trim();
|
NumberFormatException |
occurs when we try to transform a non-number value into classes which implement java.lang.Number (Integer, Double, BigDecimal...) |
String number="O"; // O instead of 0, a typo error
Integer numberInt=new Integer(number);
|
SecurityException |
it usually thrown by security manager to indicate a security violation. We can find some exceptions extending SecurityExceptions on java.security package. An example of it can be AccessControlException which is thrown, for exemple, when a user hasn't sufficient rights to access a file. |
AccessControlContext con=AccessController.getContext();
SecurityManager sm=new SecurityManager();
System.setSecurityManager(sm);
sm.checkPermission(new FilePermission("test.txt", "read,write"), con);
|
StringIndexOutOfBounds |
this exception can occur when we try to access to an non-existent String part. For example, if we have a 10-characters String and we try to get its 11th character, StringIndexOutOfBounds exception will be thrown. |
String failingString="test";
System.out.println("The 5th character is :"+failingString.substring(4, 5));
|
UnsupportedOperationException |
used to mark an operation as unsupported. Imagine that we want to put every lived day in one year into a Map<Integer, String>. The key will mean the number of the day (1-365) and the value will describe a little bit this day. Now, if somebody will try to remove past day, it should receive UnsupportedOperationException. |
class Diary<K, V> extends TreeMap<K, V>{
@Override
public V remove(final Object key){
throw new UnsupportedOperationException("You can't remove already added day!");
}
}
Map<Integer, String> diary = new Diary<Integer, String>();
diary.put(new Integer(1), "It was a good day !");
diary.remove(new Integer(1));
|
We saw that several exceptions exist in Java to handle different strange scenarios. We can use IllegalThreadStateException to handle a Thread's bad state or IllegalAccessException on trying to access to a non-visible method or field. You should use these exceptions to facilitate the understanding of your code. Is better to see explicitly that in some method only restricted values of arguments are accepted at development time, rather than discover a bug in runtime environment without knowing its origine.
Consulting
With nearly 16 years of experience, including 8 as data engineer, I offer expert consulting to design and optimize scalable data solutions.
As an O’Reilly author, Data+AI Summit speaker, and blogger, I bring cutting-edge insights to modernize infrastructure, build robust pipelines, and
drive data-driven decision-making. Let's transform your data challenges into opportunities—reach out to elevate your data engineering game today!
👉 contact@waitingforcode.com
đź”— past projects