What are Exception and Error
In the Java world, there are exceptions and errors that can be thrown by the running JVM, they are similar, but they are actually different.
- Both of them inherits from the
Throwable
. In Java, onlyThrowable
can be thrown and caught, it is the basic mechanism in Java exception handling. - The exception is expected during the application runtime, and it can and should be caught for processing. This is a possible code execution route.
- An Exception can be a checked exception or an unchecked exception.
- The checked exception must be explicitly caught, throws in the application code, it is a compile-time check Checked exception is designed to recover from the exception. As a exception designer, we usually have enough information to classify the exception.
- The unchecked exception is a kind of
RuntimeException
, such asNullpointerException
andArrayIndexOutOfBoundsException
They usually are a logic error that can be avoided, and they can be caught on demand and are not enforced at the runtime.
- However, Error is a kind of abnormal state that should not happen, once it happened, it will cause the application in an abnormal or unrecoverable state. It should not be caught by the application code, such as
OutOfMemoryError
orClassNotFoundError
.
How to Catch the Exception
Exception Class Diagram in Java
NoClassDefFoundError Example
- Source code
Java
2. Compile A.java public class A {
public static void main(String[]args) {
var b = new B();
}
static class B {
}
}
Will get two compiled classes.
3. Remove compiled classA$B.class
, then run java A
, will get NoClassDefFoundError
Bash
> java A
Exception in thread "main" java.lang.NoClassDefFoundError: A$B
at A.main(A.java:3)
Caused by: java.lang.ClassNotFoundException: A$B
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
... 1 more
ClassNotFoundException Example
Run the following source code will get ClassNotFoundException
.
Java
public class A {
public static void main(String[]args) throws ClassNotFoundException {
Class.forName("B");
}
}
Run with java A.java
.
Bash
> java A.java
Exception in thread "main" java.lang.ClassNotFoundException: B
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
at jdk.compiler/com.sun.tools.javac.launcher.Main$MemoryClassLoader.loadClass(Main.java:600)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:375)
at A.main(A.java:3)
Example to Throw or Catch Exception
Checked Exception
Java
public ExceptionTest {
// explicitly handle the checked exception
public void readFile(String file) throws FileNotFoundException {
// read file
}
public static void main(String[] args) {
}
}
try-with-resources and Multiple Catches
Java
try (BufferedReader br = new BufferedReader(…);
BufferedWriter writer = new BufferedWriter(…)) {// Try-with-resources
// do something
catch ( IOException | XEception e) {// Multiple catch
// Handle it
}
Best Practices
Don't Catch Exception or RuntimeException
Catch specfic exception instead of the above too generic exceptions.
Don't Swallow Exception
In the following example, when exception occurs in the method doWork
, the method main
can't know what is the cause.
Java
public void doWork() {
try {
// 业务代码
// …
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
doWork()
}
Throw Early, Catch Late
In snippt 1, in new FileInputStream
will throw NullPointerException
, it's hard to find the root cause when exception occurs compared with the sniipt 2.
Java
// snippt 1
public void readPreferences(String fileName){
//...perform operations...
InputStream in = new FileInputStream(fileName);
//...read the preferences file...
}
// snippt 2
public void readPreferences(String filename) {
Objects. requireNonNull(filename); // throw early
//...perform other operations...
InputStream in = new FileInputStream(filename);
//...read the preferences file...
}
Catch late enforce author to think anout how to deal with exception when caught it, there are two ways,
- Swallow exception This causes the root cause hard to find
- Throw the exception
- Create a new rxception and keep the original cause
Think About When Trying to Define a Custom Exception
- Cusotm Checked Exception
- Checked exception is designed to recover the program when exception occurs. But most of the cases are unable to recover
- It's not compatiable with funcational programming
- Don't pnclude sensitive information
- Try-catch and new exception will have extra performace Cost New Exception takes time to make snapshot of the stack trace
- Check exception in the system when performance degrad
- How to handle exception in thread executor? Log the exception into log.