I am preparing for OCP exam and I'm using Enthuware.
I got this question, what is the result of compiling and running the following code?
try {
throw new IOException();
} catch(IOException e) {
throw e;
} finally {
throw new RuntimeException();
}
Obviously, the code does compile but it throws a RuntimeException and I totally understand why.
I'm just curious why the following code doesn't compile:
try {
throw new IOException();
} catch(IOException e) {
throw e;
} finally {
test();
}
Where test() function looks like:
static final void test() throws RuntimeException {
throw new RuntimeException();
}
Even though I declared test function as final because I thought that it might the compiler is aware of overriding ...
Could someone please explain it to me?
Sorry for bad English!
-- Edit:
Just wondering why down-vote?
Error message is compile error:
Unhandled exception type IOException
And the error message when I tried to compile it is:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Unhandled exception type IOException
The first snippet compiles because the finally block runs before a value is returned or an exception thrown from the non-finally part of the method. The fact that you're throwing a RuntimeException means that you won't be throwing the IOException that you otherwise would. The compiler can work this out, and it therefore doesn't insist that you either declare or catch the IOException.
But the compiler only looks at one method at a time when it's performing this check. So the second snippet fails to compile, because the compiler doesn't check whether test() will always throw the RuntimeException. Instead, it assumes that test() might not throw the RuntimeException; and if that were to happen, the IOException would be thrown. Therefore, the compiler insists that you either catch that IOException, or declare it in a throws clause.
In java Exception handling have concept Exception propagation.
An exception is first thrown from the top of the stack and if it is not caught, it drops down the call stack to the previous method, if not caught there, the exception again drops down to the previous method, and so on until they are caught or until they reach the very bottom of the call stack. This is called exception propagation.
Rule 1: By default, Unchecked Exceptions are forwarded in calling chain (propagated).
Rule 2: By default, Checked Exceptions are not forwarded in calling chain (propagated).
try {
throw new IOException();
} catch(IOException e) {
throw e;
} finally {
throw new RuntimeException();
}
In above code snippet it's the throwing of the RuntimeException that prevents the throwing of the IOException.
try {
throw new IOException();
} catch(IOException e) {
throw e;
} finally {
test();
}
static final void test() throws RuntimeException {
throw new RuntimeException();
}
In above code snippet test() method throwing of the RuntimeException but not prevents the throwing of the IOException.
As by Rule 2 by default compiler doesn't propagate the Checked Exceptions so for that you have to declare or handle the exception.
Lets take example if you replace IOException with RuntimeException then it will not give compiletime error because by Rule 1 by default unchecked Exceptions are forwarded in calling chain (propagated).
try {
throw new RuntimeException();
} catch(RuntimeException e) {
throw e;
} finally {
test();
}
static final void test() throws RuntimeException{
throw new RuntimeException();
}
Related
This question already has answers here:
Rethrowing an Exception: Why does the method compile without a throws clause?
(5 answers)
Closed 6 years ago.
I came across a weird scenario in java today while coding around. I have a try..catch block in my method which does not have any throws clause and I am able to throw the exception object caught in the catch block. It is an object of the Exception class, hence it is not an unchecked exception. Also, It is not printing the stacktrace if exception arises instead the exception is just getting swallowed.
Below is my code example,
public class ExceptionTest {
public void test() {
try
{
// Some code which may throw exception.
}
catch(Exception ex)
{
// Compiler should ask me to have a *throws Exception* in the signature, when I am throwing an exception object.
throw ex;
}
}
}
However, if I am throwing a new exception object instead of the caught exception object, compiler is asking me to have a throws clause in the method signature.
N.B: I am facing this situation when running in Java 7 or 8.
I am wondering, where is the thrown object going to? Anyone with any idea on this please...
You'll see this if the code in the try block can't throw any checked exception. At that point, the compiler knows that the only kind of exception caught by the catch block has to be an unchecked exception, and so it can therefore be rethrown. Note that if you assigned a different value to ex within the catch block, the compiler would no longer be able to have that assurance. At the moment, ex is effectively final.
If you try to call something that is declared to throw a checked exception within the try block, the code will fail to compile as expected.
For example:
public class ExceptionTest {
public void test() {
try {
foo();
} catch(Exception ex) {
throw ex;
}
}
public void foo() throws java.io.IOException {
}
}
Gives an error of:
ExceptionTest.java:12: error: unreported exception IOException; must be caught or declared to be thrown
throw ex;
^
As for where the exception "goes" - if the code in the try block throws an unchecked exception, it gets propagated as normal. Try this:
public class ExceptionTest {
public static void main(String[] args) {
test();
}
public static void test() {
try {
String x = null;
x.length();
} catch(Exception ex) {
throw ex;
}
}
}
Running that gives the following output, as expected:
Exception in thread "main" java.lang.NullPointerException
at ExceptionTest.test(ExceptionTest.java:10)
at ExceptionTest.main(ExceptionTest.java:4)
JLS 11.2.2 documents what exceptions a statement can throw - your code will only compile if there are no checked exceptions that can be thrown.
please check that you are really throwing an exception in the code. Otherwise the compiler will not care about catching the exception.
public class ExceptionTest {
public void test() {
try
{
throw new Exception("Error");
}
catch(Exception ex)
{
// My Compiler says that I don't catch the exception
throw ex;
}
}
}
Compiler: Error:(14, 13) java: unreported exception java.lang.Exception; must be caught or declared to be thrown
I have a problem with exception handling in Java, here's my code. I got compiler error when I try to run this line: throw new MojException("Bledne dane");. The error is:
exception MojException is never thrown in body of corresponding try statement
Here is the code:
public class Test {
public static void main(String[] args) throws MojException {
// TODO Auto-generated method stub
for(int i=1;i<args.length;i++){
try{
Integer.parseInt(args[i-1]);
}
catch(MojException e){
throw new MojException("Bledne dane");
}
try{
WierszTrojkataPascala a = new WierszTrojkataPascala(Integer.parseInt(args[0]));
System.out.println(args[i]+" : "+a.wspolczynnik(Integer.parseInt(args[i])));
}
catch(MojException e){
throw new MojException(args[i]+" "+e.getMessage());
}
}
}
}
And here is a code of MojException:
public class MojException extends Exception{
MojException(String s){
super(s);
}
}
Can anyone help me with this?
A catch-block in a try statement needs to catch exactly the exception that the code inside the try {}-block can throw (or a super class of that).
try {
//do something that throws ExceptionA, e.g.
throw new ExceptionA("I am Exception Alpha!");
}
catch(ExceptionA e) {
//do something to handle the exception, e.g.
System.out.println("Message: " + e.getMessage());
}
What you are trying to do is this:
try {
throw new ExceptionB("I am Exception Bravo!");
}
catch(ExceptionA e) {
System.out.println("Message: " + e.getMessage());
}
This will lead to an compiler error, because your java knows that you are trying to catch an exception that will NEVER EVER EVER occur. Thus you would get: exception ExceptionA is never thrown in body of corresponding try statement.
As pointed out in the comments, you cannot catch an exception that's not thrown by the code within your try block. Try changing your code to:
try{
Integer.parseInt(args[i-1]); // this only throws a NumberFormatException
}
catch(NumberFormatException e){
throw new MojException("Bledne dane");
}
Always check the documentation to see what exceptions are thrown by each method. You may also wish to read up on the subject of checked vs unchecked exceptions before that causes you any confusion in the future.
Any class which extends Exception class will be a user defined Checked exception class where as any class which extends RuntimeException will be Unchecked exception class.
as mentioned in User defined exception are checked or unchecked exceptions
So, not throwing the checked exception(be it user-defined or built-in exception) gives compile time error.
Checked exception are the exceptions that are checked at compile time.
Unchecked exception are the exceptions that are not checked at compiled time
Always remember that in case of checked exception you can catch only after throwing the exception(either you throw or any inbuilt method used in your code can throw) ,but in case of unchecked exception You an catch even when you have not thrown that exception.
On the source code below I'm rethrowing an Exception.
Why is it not necessary to put the throws keyword on the method's signature?
public void throwsOrNotThrowsThatsTheQuestion() {
try {
// Any processing
} catch (Exception e) {
throw e;
}
}
This behavior appears to occur only on Java 1.7. When compiling with 1.6, I get the following compiler error message:
c:\dev\src\misc>javac -source 1.6 Main.java
warning: [options] bootstrap class path not set in conjunction with -source 1.6
Main.java:22: error: unreported exception Exception; must be caught or declared
to be thrown
throw e;
^
1 error
1 warning
But with Java 1.7, it compiles.
c:\dev\src\misc>javac -source 1.7 Main.java
c:\dev\src\misc>
... Until I actually throw an Exception in the try block:
public static void throwsOrNotThrowsThatsTheQuestion() {
try {
// Any processing
throw new IOException("Fake!");
} catch (Exception e) {
throw e;
}
Compiling...
c:\dev\src\misc>javac -source 1.7 Main.java
Main.java:22: error: unreported exception IOException; must be caught or declare
d to be thrown
throw e;
^
1 error
It looks like Java 1.7 got smart enough to detect the kind of Exception(s) that might be thrown by analyzing the try block code, where as 1.6 just saw throw e; of type Exception and gave an error just for that.
Changing it to throw a RuntimeException made it compile as expected, because as always, unchecked Exceptions don't need a throws clause:
public static void throwsOrNotThrowsThatsTheQuestion() {
try {
// Any processing
throw new RuntimeException("Fake!");
} catch (Exception e) {
throw e;
}
Compiling...
c:\dev\src\misc>javac -source 1.7 Main.java
c:\dev\src\misc>
The Explanation
Here's what's going on:
Java 7 introduced more inclusive type checking. Quoting...
Consider the following example:
static class FirstException extends Exception { }
static class SecondException extends Exception { }
public void rethrowException(String exceptionName) throws Exception {
try {
if (exceptionName.equals("First")) {
throw new FirstException();
} else {
throw new SecondException();
}
} catch (Exception e) {
throw e;
}
}
This examples's try block could throw either FirstException or SecondException. Suppose you want to specify these exception types in the throws clause of the rethrowException method declaration. In releases prior to Java SE 7, you cannot do so. Because the exception parameter of the catch clause, e, is type Exception, and the catch block rethrows the exception parameter e, you can only specify the exception type Exception in the throws clause of the rethrowException method declaration.
However, in Java SE 7, you can specify the exception types FirstException and SecondException in the throws clause in the rethrowException method declaration. 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:
(emphasis mine)
public void rethrowException(String exceptionName)
throws FirstException, SecondException {
try {
// ...
}
catch (Exception e) {
throw e;
}
}
java.lang.Exception is a checked exception so this won't work or even compile. It would work with a unckeched (java.lang.RuntimeException).
It makes absolutly no difference whether you throw an exception inside a catch block or not.
The compiler error would look something like this (depending on the compiler):
java: unreported exception java.lang.Exception; must be caught or declared to be thrown
EDIT: Java 7 can deal with such situations if you never actually throw the exception
Why is not necessary to put the throws keyword on the method's
signature?
You can put that cause your // Any processing is not throwing any checked-exception.
Example:
This compile fine.
public void throwsOrNotThrowsThatsTheQuestion() {
try {
throw new RuntimeException();
} catch (Exception e) {
throw e;
}
This won't compile, you need to add throws clause.
public void throwsOrNotThrowsThatsTheQuestion() {
try {
throw new Exception();
} catch (Exception e) {
//do something like log and rethrow
throw e;
}
}
This is working since java 7. In previous version an exception is thrown. More information rethrow in java 7
When you use throws with a method, it means that the statement which will call that method must be surrounded with a try catch block.
But if the method already includes try catch block then no thorws declaration is needed as the exception being thrown by the method is being handled there only.
The statement calling this method does not need a to be surrounded with try catch block.
Hope this clears your doubt.
throw new Exception(); is something you should never do in a catch
block, but you may have to or want to do throw new
SomeException(throwable); (preserving the full stack trace) instead
of throw throwable; in order to conform to the API of your method,
e.g. when it declares to throw SomeException but you're calling code
that might throw an IOException that you don't want to add to you
method's throws clause.
The probably most common case is new RuntimeException(throwable); to
avoid having a throws clause altogether.
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
I want a method that can throw any Throwable including sub classes of Exception. Ive got something that takes an exception, stashes it in a thread local, then invokes a class.newInstance. That class ctor declares that it throws Exception then takes the threadlocal and throws it. Problem is it does not work for the two declared Exceptions thrown by Class.newInstance() namely IllegalAccessException and InstantiationException.
Im guessing any other method using some sun.* class is just a hack and not really reliable.
Wrapping is not an option because that means catchers are catching a diff type and that's just too simple and boring...
static public void impossibleThrow(final Throwable throwable) {
Null.not(throwable, "throwable");
if (throwable instanceof RuntimeException) {
throw (RuntimeException) throwable;
}
if (throwable instanceof Error) {
throw (Error) throwable;
}
try {
THROW.set((Exception) throwable);
THROWER.newInstance();
} catch (final InstantiationException screwed) {
throw new Error(screwed);
} catch (final IllegalAccessException screwed) {
throw new Error(screwed);
} finally {
THROW.remove();
}
}
private final static Class<Impossible> THROWER = Impossible.class;
private final static ThreadLocal<Exception> THROW = new ThreadLocal<Exception>();
static private class Impossible {
#SuppressWarnings("unused")
public Impossible() throws Exception {
throw THROW.get();
}
}
From Java Puzzlers (puzzle 43):
public static void impossibleThrow(Throwable t)
{
Thread.currentThread().stop(t); // Deprecated method.
}
The book shows other methods of achieving the same problem, one is a simplified version of yours, the other exploits generic type erasure to throw any Throwable where an Error is expected.
If you want an Exception to bubble up through code not expecting that exception then just wrap it in a RuntimeException
} catch (RuntimeException e) {
throw e; // only wrap if needed
} catch (Exception e) {
throw new RuntimeException("FOO went wrong", e);
}
Remember to let the message be informative. Some day you will have to fix a bug based only on the information in the stack trace.
Wrapping an exception inside a RuntimeException (as suggested by Thorbjørn) is the way to go. However, you usually want to maintain the stacktrace of the original excpetion. Here's how:
public static void rethrow(final Throwable t)
{
if(t instanceof RuntimeException)
throw (RuntimeException) t;
RuntimeException e = new RuntimeException(t);
e.setStackTrace(t.getStackTrace());
throw e;
}
I patched javac to remove the error, compiled impossibleThrow(), renamed the source file to something that does not end in .java (which forces the next compile to use the existing .class) and used that.
There is some validity for this question as a debugging tool. Suppose you are working with some code that may have failed and you see that it (perhaps) catches certain exceptions and (perhaps) throws certain exceptions. You suspect that an unexpected exception was not caught. However, the underlying code/system is too complex and the bug is too intermittent to allow you to step through in the debugger. It can be usefull to add the throwing of an exception without changing the method in any other way. In this case, wrapping the exception with a RuntimeException would not work, because you want the calling methods to behave normally.