Will a subclass catch block catch a checked parent exception? - java

I have a method with a checked exception for a parent class, which can throw exceptions of the type parent and subclass
public void method() throws ParentException {
if( false ) throw new ParentException();
else if( true ) throw new ChildException(); // this one is thrown
}
and I have a cascade catch block, which first has the child exception
try {
method();
} catch (ChildException e) {
// I get here?
} catch (ParentException e) {
// or here?
}
Which block will catch the exception thrown? Since the method declares explicitly the ParentException only, would the ChildException be shown as an instance of ParentException?

The catch block will always catch the most specific exception available to it, working its way up from the inheritance hierarchy.
I should stress that your catch blocks must be in the inheritance hierarchy order; that is to say, you may not declare a catch block with ParentException followed by ChildException, as that is a compilation error. What you have there (in terms of catch blocks) is valid.
A more common use case of this is when handling file IO; you can first catch FileNotFoundException, then IOException, should the error be less specific than FileNotFoundException.

Related

Java: Issue with try-catch block with child class

I’m developing a web service code in Java (Eclipse Neon), I’ve two model classes for data assignment operations as shown here.
An editor is forcing me to remove try catch block from the constructor of class ‘ChatHistoryModel’ with the message: Unreachable catch block for JSONException. This exception is never thrown from the try statement
body.
If I remove the try-catch block, it will result in a code crash, when data assignment operation fails to assign data (a nil value). block if with variable is_group_chat throws null pointer exception.
How to handle this situation.
class TestHistoryModel extends TestModel {
private Boolean is_read, is_group_chat;
public TestHistoryModel(JSONObject jsonObject){
super(jsonObject);
try {
// value assignment operations
if (is_group_chat){ // Null pointer exception line
}
} catch (JSONException e) { // Error line
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class TestModel {
public TestModel(JSONObject jsonObject){
try {
// value assignment operations
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here is a snapshot of error for catch block of class - TestHistoryModel
1 JSONException
JSONException is a checked-exception. That means that you can't catch it if it is never thrown in the try statement. You can remove it as it is not necessary. Read that JLS Chapiter to get more information.
2 NullPointerException
Accessing a Boolean instance like you do if(is_group_chat) is the equivalent to if(is_group_chat.booleanValue()), as it is null, you get that NullPointerException.
Check if the instance is null before checking it
Use a boolean insteand of the auto-boxed class
See OH GOD SPIDERS answer to see an alternative condition
You are getting the "Unreachable catch block" message because JSONException is a checked exception and nothing inside your try block is declared to be able to throw that JSONException. So this Exception will never be thrown inside your try block and the catch block never used.
Since the try catch block is unnecessary and won't fix your original problem you should simply remove it.
You are getting a NullPointerException because you are using a Boolean object that is null and Java will try to autounbox it into a small boolean.
To make it NullPointerException safe change
if (is_group_chat)
to
if (Boolean.TRUE.equals(is_group_chat))
If is_group_chat is still null the method Boolean.TRUE.equals will return false.
Your try catch blocks can be removed and really are the wrong way to solve this problem.
Another solution would bee to change is_group_chat to a small boolean. But keep in mind that those will be initialized with false as a default value.
In Java, there are two types of exceptions: checked and unchecked. Checked exceptions extends from Exception while unchecked from RuntimeException. If some method is throwing checked exception, that method must have in signature throws {SomeCheckedException} unless it handles this exception in method body. This way we are saying: take extra care, this method may fail.
Here is an example how to handle checked exceptions:
public List<String> getFileLines(Path filePath) throws IOException {
// this line is throwin checked exception "IOException" therefore,
// we need to rethrow this exception since it is not handled by try-catch
// from this moment, exception handling will be left on "getFileLines" caller
return readAllLines(filePath, StandardCharsets.UTF_8);
}
public List<String> getFileLinesOrNull(Path filePath) {
try {
// here IOException is caught, so we don't have to rethrow this exception
return readAllLines(filePath, StandardCharsets.UTF_8);
} catch (IOException e) {
return null; // return null if file reading failed...
}
}
Using methods:
public void getFileLinesTest() {
try {
// we are forced to write try-catch since method signature contains "throws IOException"
List<String> lines = getFileLines(somePath);
catch (IOException e) {
System.out.println("Some error occurred");
}
}
public void getFileLinesOrNullTest() {
List<String> lines = getFileLinesOrNull(somePath);
if (lines == null) {
System.out.println("Something went wrong...");
}
}
If we are handling checked exception, but there is no line which throws this exception, than code will not compile. Compiler knows if method has "throws ..." in signature, so compiler can easily identify such an error (therefore we are calling such an exceptions as compile-time exception):
public List<String> getFileLines() {
try {
return Collections.emptyList();
} catch (IOException e) { // COMPILATION ERROR!
// handling checked exception, but Collections.emptyList(); does not throw IOException
// method signature of the Collections.emptyList() is following:
// public static List<E> emptyList();
// as you can see there is no "throws IOException"
return null;
}
}
Example above is your case, since JSONException extends from Exception, so it is checked exception, while in your code, there is no line which throws such exception in try block.
However, TestHistoryModel constructor is throwing NullPointerException which is unchecked since it extends from RuntimeException. These exceptions have no "throws" in method signature so compiler will not force us to handle such an exceptions by try-catch block. Here is an example:
public int getLength(String s) {
if (s == null) {
// NullPointerException extends from RuntimeException = we are not forced to write
// add "throws NullPointerException " in getLength signature
throw new NullPointerException();
}
return s.length();
}
Handling of runtime-exceptions is optional:
public void getLengthTest() {
int length = getLength(null); // will throw NullPointerException
try {
length = getLength(null);
} catch(NullPointerException e) {
System.out.println("null argument");
}
}
Note, we do not have to write if (s == null) in getLength method, since s.length() will automatically throw NullPointerException if argument is null
and we are trying to call method on null. Exactly this happens in your constructor, because of this line if (is_group_chat). Field is_group_chat has Boolean type. Boolean is reference-type unlike boolean which is primitive-type. Not initialized "reference-type" variables are by default null. Therefore if (is_group_chat) is if (null) which is throwing NullPointerException.

JDK 7 Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking

Prior to Java 7, if we had to rethrow an exception from a method, then we will have to do either of the 2 ways,
public void rethrowException(String exceptionName) throws FirstException, SecondException{
try {
if (exceptionName.equals("First")) {
throw new FirstException();
} else {
throw new SecondException();
}
} catch (FirstExceptione) {
throw e;
}catch (SecondException) {
throw e;
}
}
and the second one being,
public void rethrowException(String exceptionName) throws Exception {
try {
if (exceptionName.equals("First")) {
throw new FirstException();
} else {
throw new SecondException();
}
} catch (Exception e) {
throw e;
}
}
As per my understanding, New Java 7.0 has improved in a way that you can catch wide level of exception of exceptions and still keeps the narrow exceptions in the method definition, just like below code,
public void rethrowException(String exceptionName)
throws FirstException, SecondException {
try {
// ...
}
catch (Exception e) {
throw e;
}
}
The Java SE 7 compiler can determine that the exception thrown by the statement throw e must have
come from the try block, and the only exceptions thrown by the try block can be FirstException and
SecondException. Even though the exception parameter of the catch clause, e, is type Exception, the
compiler can determine that it is an instance of either FirstException or SecondException. This
analysis is disabled if the catch parameter is assigned to another value in the catch block. However,
if the catch parameter is assigned to another value, you must specify the exception type Exception in
the throws clause of the method declaration.
From Oracle docs,
In detail, in Java SE 7 and later, when you declare one or more exception types in a catch clause,
and rethrow the exception handled by this catch block, the compiler verifies that the type of the
rethrown exception meets the following conditions:
1) The try block is able to throw it.
2) There are no other preceding catch blocks that can handle it.
3) It is a subtype or supertype of one of the catch clause's exception parameters.
4) In releases prior to Java SE 7, you cannot throw an exception that is a supertype of one of
the catch clause's exception parameters. A compiler from a release prior to Java SE 7 generates
the error, "unreported exception Exception; must be caught or declared to be thrown" at the
statement throw e. The compiler checks if the type of the exception thrown is assignable to any
of the types declared in the throws clause of the rethrowException method declaration. However,
the type of the catch parameter e is Exception, which is a supertype, not a subtype, of
FirstException andSecondException.
I failed to undertand the 3rd and the 4rth point theoritically. Can someone explain me in context with the code mentioned above?
Consider following situation:
Your application throws one of the exceptions FirstException, SecondException, Exception
Exception is the supertype of FirstException, SecondException because they extend Exception.
It should also apply that SecondException extends FirstException. So FirstException is a supertype of SecondExeption and SecondException a subtype of FirstException.
Now we have a method which always throws SecondException.
First Case:
try {
[...]
} catch(SecondException se) {
// Exception gets always caught in here
[...]
} catch(FirstException fe) {
[...]
} catch(Exception e) {
[...]
}
Second Case:
try {
[...]
} catch(Exception e) {
// Exception gets always caught in here
// because Exception is supertype of all other Exception
[...]
} catch(FirstException fe) {
[...]
} catch(SecondException se) {
// is never called.
[...]
}
Do you see the point?

Java Exception Classes

I am new to Java and I was looking at exception handling. When we catch java exceptions, we declare and use an Object of the Exception class without initializing it, i.e.
catch(NullPointerException e)
e.printStackTrace();
So my question is, how are we able to use object reference e without instantiating it?
They are well instantiated:
void example() {
throw new UnsupportedOperationException("message");
} // ^^^
void demonstration() {
try {
example();
} catch (UnsupportedOperationException e) {
e.printStackTrace();
}
}
This very simple example should be pretty self explanatory...
The exception is (often) instantiated when the error occurs with a throw statement. For example,
throw new NullPointerException();
(Note that this is just an example. NPEs are not usually explicitly thrown in your own code.)
The catch clause is similar to a function that declares a parameter. Consider the function
void func(String s) {
// ...
}
func does not instantiate the s. The String is created somewhere else and passed to the function. In the same way, we create an exception with throw and it is "passed" to the catch clause kind of like a parameter.
Yes, reference e in catch(NullPointerException e) is for the possible exception thrown in code using throw new NullPointerException("some error message");
The exception is instantiated. It happens internally in the class that can potentially throw an exception. For your information, the keyword throw is responsible to create and throw the exception. Your catch method will catch the exception. You can also implement your own exceptions using this keyword.

How can I keep my thrown exception for the finally block?

I have the following code:
try {
/* etc. 1 */
} catch (SomeException e) {
/* etc. 2 */
} catch (SomeException e) {
/* etc. 3 */
} finally {
/*
* do something which depends on whether any exception was caught,
* but should only happen if any exception was caught.
*/
/*
* do something which depends on whether an exception was caught and
* which one it was, but it's essentially the same code for when no
* exception was caught.
*/
}
So, I want to keep my caught exception. Any way to do this other than assigning to a variable in every catch block?
Edit: Just to clarify, please don't post answers suggesting I use a variable scoped outside the try block. I know I can do that, the whole point of this question is finding an alternative.
Now, what I would really like to have is more flexible catch block, so that multiple catch blocks could catch the same exception, e.g. catch(Exception e) would catch everything even if it was already caught, catch(Exception e) except(NullPointerException, IllegalArgumentException) would skip the excepts. And a catch block could do catchingcontinue; to skip all other catch blocks for the same try block and catchingbreak; to skip even the finally.
Try this:
try {
// your code throwing exceptions
} catch (Exception e) { // This catch any generic Exception
// do whatever you want to do with generic exception
...
if (e instanceof SomeException) {
...
} else if (e instanceof OtherException) {
...
}
}
using java 7 you can even do this:
try {
// your code throwing exceptions
} catch (SomeException|OtherException e) { // This catch both SomeException and OtherException
// do whatever you want to do with generic exception
...
if (e instanceof SomeException) {
...
} else if (e instanceof OtherException) {
...
}
}
Keep a variable outside the scope of the catch block and assign it in the catch block.
Buy I strongly recommend that you do not do this.
Finally block should be used for resource cleanup or any similar functionality that need to be run regardless of the exceptions.
All the exception handling should be done in the catch blocks, not the finally blocks.
You will need to assign it to a variable outside the try-catch block and use it on the finally block.
Exception caughtException = null;
try {
/* etc. 1 */
} catch (SomeException e) {
caughtException= e;
} catch (SomeOtherException e) {
caughtException= e;
} finally {
if (caughtException != null) {
/*
* do something which depends on whether any exception was caught,
* but should only happen if any exception was caught.
*/
}
}
Looks like you want to do some auditing. Why don't you use some annotations and AOP to handle the behavior, of course with a good exception handling to catch those exceptions on the before or after.
What I would recommend here is that you extract the details of the exception handling out to new methods, and call those methods from catch blocks that are as specific as necessary to avoid instanceof checks. This has the advantage of not using instanceof, keeping exception handling code in catch blocks instead of in finally, and clearly separating shared exception handling code from specific exception handling code. Yes, there's some shared code between the three catch blocks, but it's a single clear line of code, which seems acceptable to me.
try {
// do work that uses resources and can generate any of several exceptions
} catch (SomeException1 e) {
standardExceptionHandler(e);
specificExceptionHandler1(e);
} catch (SomeException2 e) {
standardExceptionHandler(e);
specificExceptionHandler2(e);
} catch (Exception e) {
standardExceptionHandler(e);
} finally {
// this would include only code that is needed to cleanup resources, which is
// what finally is supposed to do.
}

Why is Class.newInstance() "evil"?

Ryan Delucchi asked here in comment #3 to Tom Hawtin's answer:
why is Class.newInstance() "evil"?
this in response to the code sample:
// Avoid Class.newInstance, for it is evil.
Constructor<? extends Runnable> ctor = runClass.getConstructor();
Runnable doRun = ctor.newInstance();
so, why is it Evil?
The Java API documentation explains why (http://java.sun.com/javase/6/docs/api/java/lang/Class.html#newInstance()):
Note that this method propagates any exception thrown by the nullary constructor, including a checked exception. Use of this method effectively bypasses the compile-time exception checking that would otherwise be performed by the compiler. The Constructor.newInstance method avoids this problem by wrapping any exception thrown by the constructor in a (checked) InvocationTargetException.
In other words, it can defeat the checked exceptions system.
One more reason:
Modern IDEs allow you to find class usages - it helps during refactoring, if you and your IDE know what code is using class that you plan to change.
When you don't do an explicit usage of the constructor, but use Class.newInstance() instead, you risk not to find that usage during refactoring and this problem will not manifest itself when you compile.
I don't know why no one provided a simple example based explanation to this, as compared to Constructor::newInstance for example, since finally Class::newInstance was deprecated since java-9.
Suppose you have this very simple class (does not matter that it is broken):
static class Foo {
public Foo() throws IOException {
throw new IOException();
}
}
And you try to create an instance of it via reflection. First Class::newInstance:
Class<Foo> clazz = ...
try {
clazz.newInstance();
} catch (InstantiationException e) {
// handle 1
} catch (IllegalAccessException e) {
// handle 2
}
Calling this will result in a IOException being thrown - problem is that your code does not handle it, neither handle 1 nor handle 2 will catch it.
In contrast when doing it via a Constructor:
Constructor<Foo> constructor = null;
try {
constructor = clazz.getConstructor();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
try {
Foo foo = constructor.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
System.out.println("handle 3 called");
e.printStackTrace();
}
that handle 3 will be called, thus you will handle it.
Effectively, Class::newInstance bypasses the exception handling - which you really don't want.

Categories

Resources