Say I have a method doSomething() which throws a checked exception, then in my main method I enclose doSomething() in a try catch.
Question:
Say I throws Exception in doSomething(). Why can't I catch (ChildException e) in my main method?
I know I can't and that I must catch Exception, but I don't understand why.
ChildException extends Exception.
If I throws ChildException and catch Exceptionthen there's no problem understandably so. Why not the other way round?
You can catch ChildException in your main method, but because the method you call is defined as throws Exception, you will also have to catch Exception, because the compiler does not know that doSomething is only throwing ChildException. If that is what you want, then you should define doSomething as throws ChildException instead.
For example with your current setup you could do:
try {
doSomething();
} catch (ChildException e) {
// handle child exception
} catch (Exception e) {
// handle other exceptions
}
As commented by MC Emperor, order of catch blocks is important, if you'd reverse the order and catch Exception first, then that block will also handle ChildException, and the ChildException-specific block will not be used.
Alternatively, change doSomething():
public void doSomething throws ChildException {
// ...
}
If your code throws ChildException child, you can catch it with Exception parent , because ChildException extends Exception, so child is assignable to parent i.e. you can write something like
Exception parent = child;
But if your code says you are throwing an Exception, the compiler takes you at face value and assumes that the exception type thrown by your method can be of any subclass of Exception or of the class Exception itself.
For example , your method may throw another ChildException2. So, in that case it is not assignable to ChildException in the catch clause of main method. The ChildException2 is neither handled nor declared.
So, the compiler doesn't allow you to continue with just catching the ChildException and asks you to either catch the type Exception or declare it.
Related
I am having trouble understanding how precise rethrow works in Java 7 and later versions. As pointed out in https://www.theserverside.com/tutorial/OCPJP-Use-more-precise-rethrow-in-exceptions-Objective-Java-7, in Java 7 and later versions we can use the throws clause, in a method declaration, with a comma-separated list of specific exceptions that the method could throw. If all these exceptions are subtypes of the general exception java.lang.Exception, we will be able to catch any of them in a catch block that catches this supertype, while letting client code (eg. a caller method) to know which of the possible subtypes exceptions actually occurred.
Initially, I thought that in order to let know client code which exception actually occurred, we needed to specify the list of specific exceptions in the throws clause. Nevertheless, in the following example the client code (the main() method) seems able to retrieve that information, even if we only specify the exception java.lang.Exception in the throws clause of the called method. Therefore, my question is:
Why the following code outputs the same, regardless of whether the throws clause of the method runException() is throws ExceptionA, ExceptionB or throws Exception ?
I am using Oracle JVM-12 in Eclipse. Thanks in advance!
class ExceptionA extends Exception{}
class ExceptionB extends Exception{}
public class RethrowingAndTypeChecking{
public static void runException(char what) throws Exception{
//public static void runException(char what) throws ExceptionA, ExceptionB{
try{
if(what == 'A')
throw new ExceptionA();
else if (what == 'B')
throw new ExceptionB();
}
catch(Exception e){
throw e;
}
}
public static void main (String args[]){
char ch;
for (int i=0;i<2;i++) {
if(i==0) ch='A';
else ch = 'B';
try{
runException(ch);
}
catch(ExceptionA e){
System.out.print("In main(), 'catch(ExceptionA e){}', caught exception: " + e.getClass());
}
catch(ExceptionB e){
System.out.print("In main(), 'catch(ExceptionB e){}', caught exception: " + e.getClass());
}
catch(Exception e){
System.out.print("In main(), 'catch(Exception e){}', caught exception: " + e.getClass());
}
System.out.println();
}
}
}
output:
In main(), 'catch(ExceptionA e){}', caught exception: class ExceptionA
In main(), 'catch(ExceptionB e){}', caught exception: class ExceptionB
What you're missing is the case where you need to handle those possible exceptions in different ways. Your code is catching individual exceptions, but it is, roughly speaking, performing the same action.
If you were to handle ExceptionA in a considerably different way from how you handle ExceptionB, then catching the broad Exception would not allow you to do that specifically:
catch(Exception e){
// something unexpected happened
// e could be an ExceptionA problem
// e could be an ExceptionB problem
// e could be any other unchecked exception
}
When the catch(Exception e){} block is entered, the exception could pretty much be anything, but you have only one generic code block to handle it.
Beside this, if the method you're calling declares specific checked exceptions, then the compiler can help you handle only those exceptions, thus adding to the predictability of the code
try{
runException(ch);
} catch(ExceptionA e){
// code specific to handling ExceptionA problems
} catch(ExceptionB e){
// code specific to handling ExceptionB problems
} catch(ExceptionC e){ //will not compile, because not declared by runException
// code specific to handling ExceptionB problems
}
Quoting #Carlos Heuberger, my code outputs the same, regardless of whether the throws clause of the method runException() is throws ExceptionA, ExceptionB or throws Exception because:
the run-time type of the exception is used to select the catch clause: see 14.20.1. Execution of try - catch
Whatever the exception reference type (in this case ExceptionA, ExceptionB or Exception) used to refer to the exception object thrown by method runException(), such method will throw objects of type either ExceptionA or ExceptionB. These objects will be assignment compatible with the catch parameters of the first two catch of the main() method.
After paragraphs 8.4.6, 11.2.3 and 14.20.1 of the Java Language Specification, I understood that what we actually specify in a throws clause of a method signature is the list of the exception reference types that will be assignment compatible with any possible exception object thrown from the method (given a class reference type we can make it point to instance objects of itself or to instance objects of its subclasses, not superclasses ). That tells any other caller method what exceptions it may have to deal with when invoking the method with the throws clause. In my code example, the advantage of using the clause throws ExceptionA, ExceptionB is that I will not need to catch java.lang.Exception in the main(). In fact, if I choose clause throws Exception in method runException() and delete the cath(Exception) block from the main() I will get a compile-time error. This is because even if we will be throwing ExceptionA or ExceptionB objects at run-time, the compiler will understand that method runException() may throw out an exception object of type Exception, which will not be assignment compatible with any of the catch parameters in the main() (Exception is a superclass of both ExceptionA and ExceptionB).
It's because, you've been throwing the Subclasses at,
try{
if(what == 'A')
throw new ExceptionA();
else if (what == 'B')
throw new ExceptionB();
}
of "Exception class" which are in turn being thrown out at,
catch(Exception e){
throw e;
}
after being assigned to "Exception class( at Exception e)", it will not make a difference if you specify throwing a Superclass type throws objectReference at
public static void runException(char what) throws Exception){
or Subclass type throws objectReferences at
public static void runException(char what) throws ExceptionA, ExceptionB){
As java compiler allows you to specify a throws ObjectReference, if it is of a Superclass of the object being thrown at the try statement.
These throws declarations are so that you list more explicitly what happens out of the method. Otherwise this is ordinary polymorphism: you use base class to combine in multiple subclasses, however you are definitely not changing the instances, this is why at runtime in both cases the exceptions are resolved to their concrete classes.
As a rule, you should never catch (Exception ex). Because this will catch RuntimeExceptions too. It sometimes makes sense to catch (Throwable t) or to use Thread.setDefaultUncaughtExceptionHandler to customize your uncaught exception handler to catch exceptions and then display them to the user. Sometimes I will catch an Exception, wrap it in a RuntimeException (or an Error) and throw that
When it comes to exceptions, you should really only be catching them when you can do something with them, or when you want to make sure that an exception doesn't cause the rest of the method to not process.
Personally I divide exceptions into 3 types
Problems in your code: This is something for you to fix
Problems with the user: For instance if you tell them to enter a number and they enter 'a', that's the user's error
"Friend" Exceptions: SocketException, for instance, is an example of this. If the socket closes and you have a thread waiting on input on it, it will throw this Exception, releasing the thread and letting you do clean-up on the socket.
In Java, is it possible to make a method that has a throws statement to be not checked.
For example:
public class TestClass {
public static void throwAnException() throws Exception {
throw new Exception();
}
public static void makeNullPointer() {
Object o = null;
o.equals(0);//NullPointerException
}
public static void exceptionTest() {
makeNullPointer(); //The compiler allows me not to check this
throwAnException(); //I'm forced to handle the exception, but I don't want to
}
}
You can try and do nothing about it:
public static void exceptionTest() {
makeNullPointer(); //The compiler allows me not to check this
try {
throwAnException(); //I'm forced to handle the exception, but I don't want to
} catch (Exception e) { /* do nothing */ }
}
Bear in mind, in real life this is extemely ill-advised. That can hide an error and keep you searching for dogs a whole week while the problem was really a cat(ch). (Come on, put at least a System.err.println() there - Logging is the best practice here, as suggested by #BaileyS.)
Unchecked exceptions in Java extend the RuntimeException class. Throwing them will not demand a catch from their clients:
// notice there's no "throws RuntimeException" at the signature of this method
public static void someMethodThatThrowsRuntimeException() /* no need for throws here */ {
throw new RuntimeException();
}
Classes that extend RuntimeException won't require a throws declaration as well.
And a word from Oracle about it:
Here's the bottom line guideline: 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.
There are 3 things you can do :
Throw a RuntimeException (or something extending a RuntimeException, like NullPointerException, IllegalArgumentException,...), you don't have to catch these as they are unchecked exceptions.
Catch the exception and do nothing (not recommended) :
public static void exceptionTest() {
makeNullPointer(); //The compiler allows me not to check this
try {
throwAnException(); //I'm forced to handle the exception, but I don't want to
} catch (Exception e) {
// Do nothing
}
}
Change exceptionTest () declaration to say that it throws an Exception, and let the method calling it catch the Exception and do what is appropriate :
public static void exceptionTest() throws Exception {
makeNullPointer(); //The compiler allows me not to check this
throwAnException(); //I'm no more forced to handle the exception
}
In Java there is two kinds of Exceptions, Checked Exceptions and Unchecked Exceptions.
Exception is a checked exception, must caught or thrown.
NullPointerException is a RuntimeException, (the compiler doesn’t forces them to be declared in the throws claus) you can ignore it, ,but it still may occur in the Runtime, and your application will crash.
From Exception documentation:
The class Exception and any subclasses that are not also subclasses of
RuntimeException are checked exceptions. Checked exceptions need to be
declared in a method or constructor's throws clause if they can be
thrown by the execution of the method or constructor and propagate
outside the method or constructor boundary.
From the RuntimeException documentation:
RuntimeException is the superclass of those exceptions that can be
thrown during the normal operation of the Java Virtual Machine.
RuntimeException and its subclasses are unchecked exceptions.
Unchecked exceptions do not need to be declared in a method or
constructor's throws clause if they can be thrown by the execution of
the method or constructor and propagate outside the method or
constructor boundary.
No, it raises a compiler error. Being a checked exception, you must either catch it or propagate it by declaring your method as potentially throwing it.
Check this and this.
Throw a RuntimeException or an exception which is derived from RuntimeException. Then the compiler will not force you to catch it.
The other answers are right, in that they correctly tell you what you should do, but it is actually possible to throw a undeclared checked exception. There are a few ways this can be done; the simplest is:
public void methodThatSecretlyThrowsAnException() {
Thread.currentThread().stop(new Exception());
}
or if your goal is to wrap an existing method that does declare its exception
public void methodThatSecretlyThrowsAnException() {
try {
methodThatAdmitsItThrowsAnException();
} catch(final Exception e) {
Thread.currentThread().stop(e);
}
}
(Needless to say, you should never do this.)
Just catch an exception and dont do any thing with it, leave it as it is and catch the generic exception in case you are not aware of the specific exception
try{
//Your logic goes here
}
catch(Exception e)//Exception is generic
{
//do nothing
}
AS I know, it's impossible in the case. Only unchecked exception, compiler can skip to check. such as RuntimeException.
You can use a loophole in the Java Compiler. Add the following code:
public RuntimeException hideThrow(Throwable e) {
if (e == null)
throw new NullPointerException("e");
this.<RuntimeException>hideThrow0(e);
return null;
}
#SuppressWarnings("unchecked")
private <GenericThrowable extends Throwable> void hideThrow0(Throwable e) throws GenericThrowable {
throw (GenericThrowable) e;
}
You can catch the exception, then invoke hideThrow with the exception to throw it without the compiler noticing. This works because of type erasure. At compile time, GenericThrowable represents RuntimeException because that is what we are passing. At run time, GenericThrowable represents Throwable because that is the basic type in the type parameter specification.
It is not advisable to avoid an exception with an empty catch block even though you are completely sure that is not going to fail under any circumstance. Sometimes, we are not aware of the human factor.
If you are sure that an exception is very unlikely to happen (if not impossible) you should create your own Exception and and wrap the unexpected exception in it.
For example:
private class UnlikelyException extends RuntimeException {
public UnlikelyException (Exception e){
super (e);
}
}
Then wrap your code with a try-catch block and throw your exception, which you don't have to catch
try {
// Your code
} catch (Exception e) {
throw new UnlikelyException(e);
}
I'm extending the class RecordingCommand from org.eclipse.emf.transaction.RecordingCommand; I need to override protected method doExecute(), the method definition does not contain any exception to throw but there is option that inside my code I have and exception and I want to catch it and raise it up, how should I handle this kind of exception, here I throw the message e but I'm not sure that this is the right way to do that.
I hope you will understand the issue since I think it more sophisticated that just throw E
i.e.throw the exception
#Override
protected void doExecute() {
try {
//my logic
} catch(Exception e) {
throw e;
}
}
You can always throw an UncheckedException from a method, which need not be declared in the throws clause.
So, you wrap your exception in any unchecked exception like that extends RuntimeException or even RuntimeException itself.
try {
//my logic
} catch(Exception e) {
throw new RuntimeException(e);
}
And just for the sake of completeness, it is a bad idea to have a single catch block for Exception, which will catch all the exceptions. Rather you should have catch block for specific type of exception your method may throw.
When a method throws and exception, do we need to have a try block inside the method?
For example,
public void foo() throws SomeException{
try{
// content of method
}
}
Is the try block required? Or, is the method able to throw a SomeException without it :
public void foo() throws SomeException{
// content of method
}
This is the case when we are not explicitly throwing a SomeException with throw.
If SomeException is a checked exception you have to either
Use a try{}catch block or
Declare that your method throws it.
You do not have to do both, either example you show in your question works just fine.
The difference is that with the try clause you handle the SomeException yourself, whereas by declaring that your own method throws it you delegate the responsability of handling the SomeException to the calling method.
When a method throws an exception it passes responsibility to handle exception to its caller.
So you don't need to handle exception if you throw it in your signature. Like as follows.
public void foo(){
try{
// content of method
}
}
but if you write it this way.
public void foo() throws SomeException{
}
you will call your method like as follows.
try{
foo();
}
You don't need a try block.
public void foo() throws SomeException {
// do some stuff
// you decide to throw the exception by yourself:
if (throwAnException) throw new SomeException();
// or you call a method that throws SomeExpection:
methodThatCanThrowSomeException();
// do more stuff
}
As long as you declare it in your signature, you're prefectly fine. The caller of your method has to handle the exception, not you. So a caller might do:
try {
foo();
} catch (SomeException e) {
// handle exception
}
Or he might pass it further along by himself.
The most problematic case you'll regularly encounter is calling a method that declares a checked exception. In the great majority of real-life cases it is not appropriate to handle that exception at the spot, but let it propagate upwards. Unfortunately, Java makes you redeclare this same exception all the way up, which creates clutter, exposes implementation details, and often also breaks the contracts of existing methods.
In such a case the way to proceed is to wrap and rethrow:
catch (RuntimeException e) {throw e;} catch (Exception e) {throw new RuntimeException(e);}
1. If the method that we are calling from a program throws an Exception, then we need to usetry/catch around the method invocation.
2. Suppose we are writing a method that throws an exception, then we need to throw new Exception object from withing the method.
3. An exception is an object of type Exception. We have Checked Exception, and Unchecked Exception (Runtime Exception).
you don't essentially need to have a try block in it
public void foo() throws SomeException {
// do some stuff
// you decide to throw the exception by yourself:
if (throwAnException) throw new SomeException();
// or you call a method that throws SomeExpection:
methodThatCanThrowSomeException();
// do more stuff
}
It seems like I can't catch exceptions in my code when the method was called from the Method.invoke method. How can catch it from inside the method itself?
void function() {
try {
// code that throws exception
}
catch( Exception e ) {
// it never gets here!! It goes straight to the try catch near the invoke
}
}
try {
return method.invoke(callTarget, args);
}
catch( InvocationTargetException e ) {
// exception thrown in code that throws exception get here!
}
Thanks!
You can get the real cause of the MethodInvocationException by checking its getCause() method that will return the exception thrown from function()
Note: you might need to call getCause() recursively on the returned exceptions to arrive at yours.
Note: getCause() returns a Throwable, which you will have to check for its actual type (e.g. instanceof or getClass())
Note: getCause() returns null if no more "cause" is available -- you have arrived at the base cause of the execption thrown
Update:
The reason why the catch() in function() is not getting executed is that xxxError is not an Exception, so your catch won't catch it -- declare either catch(Throwable) or catch(Error) in function() if you don't want to declare all specific errors -- note that this is usually a bad idea (what are you going to dio with an OutOfMemoryError?.
One reason that you can't catch UnsatisfiedLinkError with Exception is that UnsatisfiedLinkError is not a subclasses of Exception. In fact, it is a subclass of Error.
You should be careful about catching Error exceptions. They almost always indicate that something really bad has happened, and in most cases it is not possible to recover from them safely. For instance, an UnsatisfiedLinkError means that the JVM can't find a native library ... and that whatever depended on that library is (probably) unusable. Generally speaking. Error exceptions should be treated as fatal errors.
MethodInvocationException means you're calling the method wrong, it shouldn't have even gotten to inside your try block. From the docs:
Signals that the method with the specified signature could not be invoked with the provided arguments.
Edit: That's if this is the Spring MethodInvokationException, the Apache Velocity one does wrap function exceptions.
You throw exceptions as normal. The fact its inside an invoke makes no difference.
public class B {
public static void function() {
try {
throw new Exception();
} catch (Exception e) {
System.err.println("Caught normally");
e.printStackTrace();
}
}
public static void main(String... args) throws NoSuchMethodException, IllegalAccessException {
Method method = B.class.getMethod("function");
Object callTarget = null;
try {
method.invoke(callTarget, args);
} catch (InvocationTargetException e) {
// should never get called.
throw new AssertionError(e);
}
}
}
prints
Caught normally
java.lang.Exception
at B.function(B.java:15)
... deleted ...
at B.main(B.java:26)
... deleted ...