Exception - sivakrsna/Java-Interview GitHub Wiki
Exception
An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions.
When an error occurs within a method, the method creates an object and hands it off to the runtime system. The object, called an exception object, contains information about the error, including its type and the state of the program when the error occurred. Creating an exception object and handing it to the runtime system is called throwing an exception.
Checked exceptions
A checked exception is an exception that occurs at the compile time, these are also called as compile time exceptions. These exceptions cannot simply be ignored at the time of compilation, the programmer should take care of (handle) these exceptions.
All exceptions are checked exceptions, except for those indicated by Error, RuntimeException, and their subclasses.
Unchecked exceptions
An unchecked exception is an exception that occurs at the time of execution. These are also called as Runtime Exceptions. These include programming bugs, such as logic errors or improper use of an API. Runtime exceptions are ignored at the time of compilation.
Use checked exceptions for recoverable conditions and runtime exceptions for programming errors
If a client can reasonably be expected to recover from an exception, make it a checked exception. If a client cannot do anything to recover from the exception, make it an unchecked exception.
Error Class
When a dynamic linking failure or other hard failure in the Java virtual machine occurs, the virtual machine throws an Error. Simple programs typically do not catch or throw Errors.
Exception Class
Most programs throw and catch objects that derive from the Exception class. An Exception indicates that a problem occurred, but it is not a serious system problem. Most programs you write will throw and catch Exceptions as opposed to Errors.
The Java platform defines the many descendants of the Exception class. These descendants indicate various types of exceptions that can occur. For example, IllegalAccessException signals that a particular method could not be found, and NegativeArraySizeException indicates that a program attempted to create an array with a negative size.
One Exception subclass, RuntimeException, is reserved for exceptions that indicate incorrect use of an API. An example of a runtime exception is NullPointerException, which occurs when a method tries to access a member of an object through a null reference.
What is the purpose of the throw and throws keywords?
The throws keyword is used to specify that a method may raise an exception during its execution. It enforces explicit exception handling when calling a method:
public void simpleMethod() throws Exception {
// ...
}
The throw keyword allows us to throw an exception object to interrupt the normal flow of the program. This is most commonly used when a program fails to satisfy a given condition:
if (task.isTooComplicated()) {
throw new TooComplicatedException("The task is too complicated");
}
throws keyword is used with method signature to declare the exceptions that the method might throw whereas throw keyword is used to disrupt the flow of program and handing over the exception object to runtime to handle it.
What is the difference between an exception and error?
An exception is an event that represents a condition from which is possible to recover, whereas error represents an external situation usually impossible to recover from.
All errors thrown by the JVM are instances of Error or one of its subclasses, the more common ones include but are not limited to:
- OutOfMemoryError – thrown when the JVM cannot allocate more objects because it is out memory, and the garbage collector was unable to make more available
- StackOverflowError – occurs when the stack space for a thread has run out, typically because an application recurses too deeply
- ExceptionInInitializerError – signals that an unexpected exception occurred during the evaluation of a static initializer
- NoClassDefFoundError – is thrown when the classloader tries to load the definition of a class and couldn’t find it, usually because the required class files were not found in the classpath
- UnsupportedClassVersionError – occurs when the JVM attempts to read a class file and determines that the version in the file is not supported, normally because the file was generated with a newer version of Java
Although an error can be handled with a try statement, this is not a recommended practice since there is no guarantee that the program will be able to do anything reliably after the error was thrown.
Does finally always execute in Java?
Yes, finally will be called.
The only times finally won't be called are:
- If you invoke System.exit();
- If the JVM crashes first;
- If there is an infinite loop (or some other non-interruptable, non-terminating statement) in the try block;
- If the OS forcibly terminates the JVM process; e.g. "kill -9 " on UNIX.
- If the host system dies; e.g. power failure, hardware error, OS panic, etc.
What is OutOfMemoryError in Java?
OutOfMemoryError in Java is a subclass of java.lang.VirtualMachineError and it’s thrown by JVM when it ran out of heap memory. We can fix this error by providing more memory to run the java application through java options.
$>java MyProgram -Xms1024m -Xmx1024m -XX:PermSize=64M -XX:MaxPermSize=256m
What is difference between final, finally and finalize in Java?
final and finally are keywords in java whereas finalize is a method.
final keyword can be used with class variables so that they can’t be reassigned, with class to avoid extending by classes and with methods to avoid overriding by subclasses, finally keyword is used with try-catch block to provide statements that will always gets executed even if some exception arises, usually finally is used to close resources. finalize() method is executed by Garbage Collector before the object is destroyed, it’s great way to make sure all the global resources are closed.
Out of the three, only finally is related to java exception handling.
ClassNotFoundException vs. NoClassDefFoundError
ClassNotFoundException is an exception that occurs when you try to load a class at run time using Class.forName() or loadClass() methods and mentioned classes are not found in the classpath.
NoClassDefFoundError is an error that occurs when a particular class is present at compile time, but was missing at run time.
The difference from the Java API Specifications is as follows.
For ClassNotFoundException:
Thrown when an application tries to load in a class through its string name using:
The forName method in class Class. The findSystemClass method in class ClassLoader. The loadClass method in class ClassLoader. but no definition for the class with the specified name could be found.
For NoClassDefFoundError:
Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found.
The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found.
Java runtime throws ClassNotFoundException while trying to load a class at runtime only and the name was provided during runtime. In the case of NoClassDefFoundError, the class was present at compile time, but Java runtime could not find it in Java classpath during runtime.
The difference between the two is that one is an Error and the other is an Exception. With NoClassDefFoundError is an Error
Can we have an empty catch block?
We can have an empty catch block but it’s the example of worst programming. We should never have empty catch block because if the exception is caught by that block, we will have no information about the exception and it wil be a nightmare to debug it. There should be at least a logging statement to log the exception details in console or log files.
Java Exception Handling Best Practices
Some of the best practices related to Java Exception Handling are:
- Use Specific Exceptions for ease of debugging.
- Throw Exceptions Early (Fail-Fast) in the program.
- Catch Exceptions late in the program, let the caller handle the exception.
- Use Java 7 ARM feature to make sure resources are closed or use finally block to close them properly.
- Always log exception messages for debugging purposes.
- Use multi-catch block for cleaner close.
- Use custom exceptions to throw single type of exception from your application API.
- Follow naming convention, always end with Exception.
- Document the Exceptions Thrown by a method using @throws in javadoc.
- Exceptions are costly, so throw it only when it makes sense. Else you can catch them and provide null or empty response.