I've coded a method with a catch-all handler, but I need to rethrow the exception as if it were unhandled, so that a caller (much) further up the call stack can handle it. The trivial way to do this is simply:
try {
...
} catch (Exception ex) {
// do something here...
// and rethrow
throw ex;
}
But the problem is that, because of the throw statement, Java requires this method to declare itself as throws Exception, which in turn, requires all the callers to handle the exception or declare themselves as throws Exception. And so on up the call chain...
Is there any simple way to rethrow the exception as if the current method did not handle it?
You have exactly two options with (checked) exceptions:
Handle them in the method via a try/catch (which may include rethrowing as a different exception type)
Declare that the method throws the exception.
If you want to rethrow the exception as if this method did not catch it, your only option is 2.
Note: you only want to catch (Exception e) if a method in the try block actually throws Exception. Otherwise, catch the specific exception types.
You could do what #radoh has said and just wrap into a RuntimeException, but one downside of this is your stacktrace is now polluted and will show the offending line to be where you declare throw new RuntimeException(ex).
An alternative is to use Lomboks SneakyThrows mechanism, like this:
public static void main(String[] args) {
methodWithException();
}
private static void methodWithException() {
try {
throw new Exception("Hello");
} catch (Exception e) {
Lombok.sneakyThrow(e);
}
}
Your stacktrace will remain intact, but you no longer need to declare throws Exception.
It's worth reading the documentation on why you should/shouldn't do this
Related
Let's suppose I have this class:
public class Obj1{
...
public void do_Something(int someParameter) throws SomeException {
if(...) throw new SomeException();
...
}
...
}
then, somewhere
public class Obj2{
...
public void do_SomeOtherThing(Obj1 obj1){
obj1.do_Something();
//apparently the only solution is try-catching it directly, even if I'm not in the main...
...
}
I've learned that exceptions should only be thrown by METHOD, and catched by MAIN, so, my question is: is try-catch the unique way to handle sub-method exceptions, or the most external method (do_SomeOtherThing) will throw it, so that I can try-catch it directly in main, deleting the try-catch in Object2 class?
Basically, can I do as follows?
public static void main(String[] args){
Object1 obj1 = new Object1();
Object2 obj2 = new Object2();
try{
obj2.do_SomeOtherThing(obj1);
}
catch(SomeException e){
...
}
}
or not?
A checked exception is part of the contract that a method has with its caller, and a thrown exception will always need to be handled one way or another.
The correct answer depends on the exact situation:
The caller can handle the exception:
String getStringFromRemoteServer() throws IOException { ... }
String getConfigString() {
try {
return getStringFromRemoteServer();
} catch (IOException e) {
LOG.warn("Failed to contact server, using local version.", e);
return getLocalString();
}
}
In this case we have an alternative source of the data we need, so if the preferred method fails we catch the exception, log it (so that we know a problem exists with our network) and call the alternative.
The exception is fatal, and we don't want any function higher in the call tree to try to handle it.
Configuration parseConfiguration(String configString) throws ParseException { ... }
void loadConfiguration() {
try {
this.globalConfig = parseConfiguration(getConfigString());
} catch (ParseException e) {
throw new RuntimeException("Corrupted config", e);
}
}
In this case an exception means that the configuration of our application is fatally broken. There is no point in trying to handle this error, and no point in any of our callers trying to handle it, so declaring throws on loadConfiguration() would just be confusing clutter. We wrap the exception in a RuntimeException and rethrow it. Note that we don't log it -- there will be some top level reporting of uncaught exceptions, so logging it here would be repetition.
It is still valuable to have parseConfiguration() throw a checked exception, because when we are calling it from the interactive configuration editor we catch the exception and display an error message to the user.
Maybe our caller can handle the exception.
int stringToInteger(String s) throws BadNumberException { ... }
String decimalStringToHexString(String s) throws BadNumberException {
return intToHex(stringToInteger(s));
}
In this case we are not changing the meaning of the exception -- decimalStringToHexString is converting a number from a string, and one possible outcome is that the string is illegal. Our caller needs to be aware of that as a possible outcome, just as callers of stringToInteger() are, so we simply declare the exception and let our caller handle it. Our caller knows the context they are using the number in, so they can decide how to handle the exception.
A couple of rules:
Never completely ignore an exception (OK, maybe InterruptedException). If you write try { ... } catch (Exception e) {} the empty catch clause will make it hard to spot why your code doesn't work.
When you wrap an exception, always include the original exception as the cause.
Sonar complains when catching the generic type Exception, but sometimes we need to do some general exception handling for ALL (even not yet recognized) exception types. What is the solution to pass this sonar check?
Unless you are invoking a method which throws Exception, there is no need to catch Exception: catch the exceptions you know about, and the compiler will tell you when you have to start handling another one.
The problem with catching "not yet recognized" Exceptions is that you lose the signal that you have to handle a new exception in a special way.
For example:
void someMethod() {
// Do stuff.
}
void callIt() {
try {
someMethod();
} catch (Exception e) {
// ...
}
}
If someMethod is now changed so that it throws, say, an InterruptedException:
void someMethod() throws InterruptedException {
Thread.sleep(1000);
// Do stuff.
}
you aren't told by the compiler that you need to add handling for the InterruptedException in callIt(), so you will silently swallow interruptions, which may be a source of problems.
If, instead, you had caught RuntimeException, or RuntimeException | IOException | OtherExceptionYouAlreadyKnowAbout, the compiler would flag that you had to change your code to handle that InterruptedException as well; or, that you can't change the signature of someMethod(), and the checked exception has to be handled there.
I got this method:
public void foo(){
int test = 5/0;
}
And I call it like this:
try {
foo();
} catch (Exception e){
e.printStackTrace();
}
This catches the ArithmeticException, but I have seen cases where I call a method inside try-catch, but it doesn't catch the exception. Is there a specific situation in which the exception may not be caught?
Here is an example to clarify the question:
Does the try-catch block in ActivityA catches the exception in ActivityB? I know the answer is negative. But I want to know the logic behind this.
public class ActivityA extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
try {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
startActivity(new Intent(this, ActivityB.class));
} catch (Exception e){
e.printStackTrace();
}
}
}
And ActivityB:
public class ActivityB extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
int x = 5/0
}
}
To all cool guys who think this is a duplicate question, please give me a link to a question on StackOverFlow that answers to this very clear question: Does a try-catch catches exceptions that happens in a method which is called inside it?
What may have happened is that you tried to catch in an exception that was not the one that was fired.
In the case of ArithmeticException, if you fire one, for example, NumberFormatException, it won't hold the Exception and will stop your application.
If you catch Exception, Exception itself and all exceptions that are a subtype of Exception will be caught by that block. In Java that will be the so called "checked exceptions".
However, you will not catch those "exceptions" that are only a subtype of Throwable. To be precise, those are not acctually exceptions. They are errors. It is also possible to catch them in a try-catch statement.
Not that neither catching Exception nor Throwable is a good practice. Always catch the specific exceptions and errors you are expecting.
If you specify an exception to be caught, e.g
public void foo(numb, divisor) throws ArithmeticException {
if (divisor == 0) throw new ArithmeticException();
int ans = num / divisor;
}
#Test
public void tesfooWithZeroDivisor() {
try {
foo(5, 0);
} catch (ArithmeticException e) {
System.out.println("Can't divide by zero");
}
}
In this case, you're specifying that you want an ArithmeticException to be caught if thrown. In the event that no ArithmeticException is thrown but a different exception such as IllegalArgumentException, then it will not catch an IllegalArgumentException because you only specify ArithmeticException.
In your case, you used catch (Exception e) which means you didn't specify an exception so it will catch any exception that got thrown regardless.
Is there a specific situation in which the exception may not be caught?
Some situations spring to mind:
The code (e.g. the call to foo()) was not executed. So the exception was not thrown.
The exception was thrown by different code; e.g. in your example, the foo() method is called from somewhere else; e.g. on a different thread stack.
The exception was caught further up the call chain.
You have declared your own exception (e.g. my.pkg.ArithmeticException) and you are catching a different exception to the one thrown as a result
If you do funky things with classloaders, it is possible to load the same class more than once. If you do that, you will have types that have the same name, but are in fact different. If you did that with an exception class, the instanceof test that the handler performs may fail to match.
Does a try-catch catches exceptions that happens in a method which is called inside it?
Yes. If you have implemented it properly; see above.
If you want chapter and verse, read JLS 14.20.
Concerning your updated example, I would not expect the exception handler for ActivityA to see exceptions thrown in ActivityB.onCreate. I would expect onCreate() to be called by a different thread.
You can confirm this by catching the exception in ActivityB.onCreate and looking at the stacktrace.
I'm beginner in Java and Android. My problem is when I use setDefaultUncaughtExceptionHandler in my code, some functions still need a try/catch block surrounding it, but I want throw all my exceptions to UncaughtException thread.
public class MyAlarmReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Thread.setDefaultUncaughtExceptionHandler(new UnCaughtException(context));
try
{
String imageURL = MyWebService.readFeed();
DownloadAndSet.downloadFile(imageURL);
}
catch(Throwable e)
{
throw new RuntimeException(e);
}
Toast.makeText(context, "Alarm Triggered", Toast.LENGTH_LONG).show();
}
}
Java distinguishes checked and unchecked exceptions. Checked Exceptions have to be caught, no matter what.
Correction: Or you have to add the throws clause to the method. This postpones the urge to catch that exception to the caller of your method.
If you want them to be handled in the UncaughtExceptionHandler, you can "forward" them:
try{
// blah "throws some checked exception type"
} catch ( Throwable e ) {
// throw e; <- This will not work :( unless you add the "throws" clause.
throw new RuntimeException(e);
}
Unfortunately, just throwing the same Exception won't work, because you'd have to add the throws clause, which you do not want. You'll have to wrap it in a RuntimeException.
All checked exceptions in your code must be caught.
Further reading on checked vs unchecked exceptions:
http://www.javapractices.com/topic/TopicAction.do?Id=129
http://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html
When you call a method that throws an exception, requires you to either handle the exception using try/catch or throw the same exception.
As you don't want to handle the exception in your code and want all exceptions to be handled by your Default Exception handler so you need to add throws to all your methods where you don't want to catch the exception.
The documentation says:
Set the default handler invoked when a thread abruptly terminates due to an uncaught exception, and no other handler has been defined for that thread.
It doesn't relate to exceptions you have to catch. An example of an exception you have to catch/throw is IOException. An example of an exception you don't is NullPointerException.
So if your code causes a NullPointerException, the default handler will deal with it. If your code (potentially) causes an IOException, you have to deal with it then and there (either by catching or throwing).
What I have always done in my programs is create a exception handler method and call it every time I make a try/catch block. Many times I have had Thread.sleep() methods and I just send the exception to a common place to do "global" handling. In your global exception handler, you can also refer to this method.
Keep in mind that you might not always want to use this method because things like file streams might throw errors if a file already exists and you would want to take a different approach such as naming it something else than just stopping the program.
public static void main(String[] args) {
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
catchException(e);
}
});
try {
Thread.sleep(1000);// Just an example of a possible exception thrower
}
catch (InterruptedException e) {
catchException(e);
}
}
public static void catchException(Throwable e) {
// Deal with the exception here
System.out.println("Oh no! You broke the program!!!");
System.out.println("Here is the error btw: " + e.getMessage());
}
If you are using Eclipse, you can set the default automatic code generation for try/catch blocks to automatically include this method:
You can also set project specific settings if you don't want this behaviour for all of your projects.
In trying to refactor some I code I attempted to throw the exception in the catch clause like so -
try {
....
}
catch(Exception exception){
.....
throw exception
}
However when I attempted to throw the exception on line "throw exception" the compiler complained with a message that I needed to surround my throw clause in a new try/catch like so -
try
{
....
}
catch (Exception exception)
{
.....
try
{
throw exception
}
catch (Exception e2)
{
...
}
}
Why does the compiler require this and what use does it provide ?
Thanks
The exception java.lang.Exception is a checked exception. This means that it must either be declared in the throws clause of the enclosing method or caught and handled withing the method body.
However, what you are doing in your "fixed" version is to catch the exception, rethrow it and then immediately catch it again. That doesn't make much sense.
Without seeing the real code, it is not clear what the real solution should be, but I expect that the problem is in the original try { ... } catch handler:
If possible, you should catch a more specific exception at that point, so that when you rethrow it, it is covered by the method's existing throws list.
Alternatively, you could wrap the exception in an unchecked exception and throw that instead.
As a last resort, you could change the signature of the method to include Exception in the throws list. But that's a really bad idea, because it just pushes the problem off to the caller ... and leaves the developer / reader in the position of not knowing what exceptions to expect.
In Java, there is a distinction between checked and unchecked exceptions. An unchecked exception can essentially be thrown at any place in code and, if it's not caught somewhere, it will propagate up to the entry point of your application and then stop the process (usually with an error message and stack trace). A checked exception is different: The compiler won't let you just let it propagate, you need to either surround any code which might throw a checked exception with try-catch blocks (and "throw exception" is the simplest case if exception is an instance of a checked exception class) or you must mark the method which contains the call to code that might throw a checked exception with a "throws" declaration. If the desired behaviour is to throw an unchecked exception, then you'll need to wrap the exception in a RuntimeException. If the desired behaviour is to keep the exception checked, then you'll need to add a throws declaration to your current method.
In your original code, nothing catches the thrown exception. I would imagine you either have to specify that your function throws an exception or have another try/catch block as the compiler suggests to catch it.
Instead of
public void yourFunction(){
try {
....
}
catch(Exception exception){
.....
throw exception
}
}
try
public void yourFunction() throws Exception{
try {
....
}
catch(Exception exception){
.....
throw exception
}
}
My guess is that your trying to throw an exception sub class that isn't declared by the method as an exception type it can throw.
The following example works
package test.example;
public class ExceptionTest {
public static void main(String[] args) throws Exception{
try {
int value = 1/0;
} catch (Exception e) {
System.out.println("woops the world is going to end");
throw e;
}
}
}
However this example will give an error.
package test.example;
public class ExceptionTest {
public static void main(String[] args) throws RuntimeException{
try {
int value = 1/0;
} catch (Exception e) {
System.out.println("woops the world is going to end");
throw e;
}
}
}
Note in the second example I'm simply catching Exception not RuntimeException, it won't compile as I throw Exception which is an undeclared throws, even though I do declare RuntimeException.
Yes the exception is a RuntimeException but the compiler doesn't know that.
Just thought of a third working example to show you. This one also works because your throwing the same type as you declare. (note the only change is the catch block)
package test.example;
public class ExceptionTest {
public static void main(String[] args) throws RuntimeException{
try {
int value = 1/0;
} catch (RuntimeException e) {
System.out.println("woops the world is going to end");
throw e;
}
}
}
You need to understand the differences between all three of these answers