I am running the following code:
import java.io.FileNotFoundException;
import java.io.IOException;
class Basic1 {
int c;
void calculation(int a, int b) throws Exception {
c = a / b;
}
}
class Basic extends Basic1 {
void calculation(int a, int b) throws IOException {
c = a / b;
RuntimeException ae = new ArithmeticException();
throw ae;
}
public static void main(String[] args) {
int a = 10;
int b = 0;
int c;
Basic ba = new Basic();
try {
ba.calculation(a, b);
} catch (IOException e) {
System.out.println("Zero can't be there in the denominator. : IoException");
} catch (ArithmeticException e) {
System.out.println("Zero can't be there in the denominator. : Arthimetic Exception");
} catch (Exception e) {
System.out.println("Zero can't be there in the denominator. : Exception");
}
}
}
The program is compiling successfully and outputting "Zero can't be there in the denominator. : Arthimetic Exception" (output is as expected).
My question is how is the program able to compile successfully? Why am I not getting an error when I throw an IOException while inside calculation() I am creating a RuntimeException object?
My second question is given that the program enters the catch (ArithmeticException e) clause, is the compiler deciding at run time which catch will execute? Do I understand correctly?
For your first question, methods using the throws E (where E is some arbitrary checked exception) construct don't have to throw anything. All it means is that anyone calling your method has to be able to handle E, which allows your method to throw E without handling it. This would otherwise be a compilation error. Usually, the documentation of your method specifies when E is thrown. In the words of the JLS:
Essentially, for each checked exception that can result from execution of the body of a method or constructor, a compile-time error occurs unless its exception type or a supertype of its exception type is mentioned in a throws clause in the declaration of the method or constructor.
This doesn't say you must throw the given checked exception within the method body. Note that you can use throws with unchecked exceptions, but this has no effect on the program, as unchecked exceptions may be thrown anywhere without being handled. That's the point of them.
In your code, you throw a RuntimeException. Any class extending RuntimeException (including itself) is unchecked by definition. ArithmeticException is one of these, so you may assign it to a variable of type RuntimeException and then throw it without specifying it in the throws clause.
For your second question, I'll assume that the compiler doesn't optimise away the various catch clauses. In that case, no, the catch which is executed is not determined at compile time. When any exception is thrown in your program, it propagates up the stack until it is caught. If it isn't, it halts execution and the stack trace is printed to System.err. Since an ArithmeticException is thrown, the first catch clause does not match but the second one does, so is executed. The third one (catch (Exception e)) would match, but order matters with catch clauses and only one is executed, so that clause is not executed here.
However, in this case, it is not inconceivable that the compiler optimises away your catch clauses and directs the program straight to the code in the catch (ArithmeticException e) clause, as your method will always throw ArithmeticException. It must be considered, however, that any line of code may throw some obscure error like OutOfMemoryError; the compiler must allow for such edge cases when optimising.
Related
When there are methods that throw exceptions and you know these exceptions will not be thrown, what should you do?
Many times I see people just logging the exception, but I wonder if there is a build in exception in java that means something like: "This exception should not have been thrown".
For example, imagine I have a code that calls StaticClass.method(someObject) and this method throws a SpecificException when someObject is not valid. What should you do in the catch block?
try {
StaticClass.method(someobject);
} catch (SpecificException e) {
// what should I do here?
}
If when calling the method you know for sure that it will not throw an exception because of previous checks you should throw a RuntimeException wrapping the SpecificException.
try {
StaticClass.method(someobject);
} catch (SpecificException e) {
//This is unexpected and should never happen.
throw new RuntimeException("Error occured", e);
}
Some methods already throw a RuntimeException when they fail to perform their purpose.
//Here we know for sure that parseInt(..) will not throw an exception so it
//is safe to not catch the RuntimeException.
String s = "1";
int i = Integer.parseInt(s);
//Here instead parseInt(..) will throw a IllegalArgumentException which is a
//RuntimeException because h is not a number. This is something that should
//be fixed in code.
s = "h";
i = Integer.parseInt(s);
RuntimeExceptions don't require a try/catch block and the compiler will not be mad at you for not catch them. Usually they are thrown where something in your app code is wrong and should be fixed. Anyway there are cases where catching a RuntimeException is useful.
I am trying to follow this tutorial JUnit 5: How to assert an exception is thrown?
I use Java 10, IntelliJ 2018 and Junit 5.
I make a calculator app that adds 2 fractions. It checks whether the input has 0 in the denominator.
When I run the test The exception Message get printed out "Undefined Math Expression" but my IDE says "Expected java.lang.Throwable to be thrown, but nothing was thrown." I think there is some problem with the scope of my code? I'm a newbie, please be kind. I provided the code and the test below:
public class Calculator {
public static int[] calculate (int firstNumerator, int firstDenominator, int secondNumerator, int secondDenominator) {
String exceptionMessage = "Undefined Math Expression";
int resultNumerator;
int resultDenominator;
int[] result = new int[2];
resultNumerator = (firstNumerator * secondDenominator) +
(secondNumerator * firstDenominator);
resultDenominator = firstDenominator * secondDenominator;
try {
if (resultDenominator == 0) {
throw (new Throwable(exceptionMessage));
} else {
result[0] = resultNumerator;
result[1] = resultDenominator;
}
} catch (Throwable e) {
System.out.println(e.getMessage());
}
return result;
}
}
The test:
class CalculatorTest {
#Test
void denominatorContainsZero() {
assertThrows(Throwable.class, () -> {
Calculator.calculate(0,0,0,0);
});
}
}
The misunderstanding here appears to be in what JUnit can actually see.
JUnit isn't magical: it's just plain old Java. It can't see inside your methods to see what they are doing. All it can see is what any other code can see when it executes a method: the return value and uncaught exceptions (as well as any side effects of the method, if they are visible to the calling code).
Your method here doesn't throw an exception from the perspective of a caller: internally, it throws the exception, but it catches and handles it.
If you want JUnit to test that an exception is thrown, you need to not catch that exception.
It is never (*) the right thing to do to throw an exception and then catch and handle it yourself. What's the point? You can simply do the thing you do to handle it, without throwing the exception. Exceptions are expensive to throw, because of the need to capture the entire stack trace.
Throwable is never (*) the right exception to throw. It's the exception "equivalent" of returning Object: it conveys no type information about the exception to the caller, who then either has to do a lot of work to try to handle it; or, more realistically, should just propagate it themselves. IllegalArgumentException is the right exception to throw here, if you actually needed to throw (and not catch) an exception.
Throwable is rarely the right thing to catch. Throwable is a supertype of both Exception and Error, so you might unintentionally catch an Error, like OutOfMemoryError, which shouldn't be caught because there is nothing reasonable to do except crash your program. Catch the most specific type you can; which also means that you should throw the most specific type you can (or, at least, a type appropriate to the abstraction).
(*) This is "never" as in "ok, there are a limited number of circumstances where it may be appropriate". But unless you understand what these are, don't.
The Throwable is catched by try catch block, so Junit can not access it. Try remove the try catch block.
You are not actually throwing exception, you are catching it. For this to work, you should remove try catch block.
try {
throw new FileNotFoundException();
} catch (IOException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
Can someone tell me why the second catch block is not considered as unreachable code by the compiler? But in the following case:
try {
throw new FileNotFoundException();
} catch (Exception e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
The second catch block is considered unreachable?
After all, FileNotFoundException comes under IOException, just as it comes under Exception.
Edit Please clarify:
The compiler will know an exception is thrown by a method based on the method's throws clause. But it may not necessarily know the specific type of exception (under that class of exception). So if a method throws exception 'A', compiler won't know if the actual exception is 'A' or a subtype of 'A' because this is only determined at runtime. The compiler however will know that an exception of type 'X' is never thrown, so giving a catch block for X is erroneous. Is this right?
The compiler cannot assume that the only possible exception thrown from your try block will be a FileNotFoundException. That's why it doesn't consider the 2nd catch block to be unreachable in your first code sample.
What if, for some unknown reason, a RuntimeException gets thrown while creating the FileNotFoundException instance (entirely possible)? What then?
In your first code sample, that unexpected runtime exception would get caught by the 2nd catch block, while the 1st block would take care of the FileNotFoundException if it gets thrown.
However, in your 2nd code sample, any and all exceptions would get caught by the 1st catch block, making the 2nd block unreachable.
EDIT:
To better understand why the catch(Exception e) block in your first code is not considered unreachable by the compiler, try the following code, and notice how the the 2nd catch is definitely reachable:
public class CustomIOException extends IOException {
public CustomIOException(boolean fail) {
if (fail) {
throw new RuntimeException("the compiler will never know about me");
}
}
}
public static void main(String[] args) {
try {
throw new CustomIOException(true);
} catch(IOException e) {
System.out.println("Caught some IO exception: " + e.getMessage());
} catch(Exception e) {
System.out.println("Caught other exception: " + e.getMessage());
}
}
Output:
Caught other exception: the compiler will never know about me
TL;DR
The compiler considers that FileNotFoundException() may not be the only Exception thrown.
Explaination
JLS§11.2.3 Exception Checking
A Java compiler is encouraged to issue a warning if a catch clause can
catch (§11.2) checked exception class E1 and the try block
corresponding to the catch clause can throw checked exception class
E2, a subclass of E1, and a preceding catch clause of the immediately
enclosing try statement can catch checked exception class E3 where E2
<: E3 <: E1.
That means that if the compiler considers that the only exception possibly thrown by your catch block is a FileNotFoundException(), it will warn you about your second catch block. Which is not the case here.
However, the following code
try{
throw new FileNotFoundException();
} catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e){ // The compiler warns that all the Exceptions possibly
// catched by IOException are already catched even though
// an IOException is not necessarily a FNFException
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
This happens because the compiler evaluates the try block to determine which exceptions has the possibility to be thrown.
As the compiler does not warn us on Èxception e, it considers that other exceptions may be thrown (e.g RunTimeException). Since it is not the compiler's work to handle those RunTimeExceptions, it lets it slip.
Rest of the answer is intersting to read to understand the mechanism behind exception-catching.
Schema
As you may see, Exception is high in the hierarchy so it has to be declared last after IOException that is lower in the hierarchy.
Example
Imagine having an IOException thrown. As it is inherited from Exception, we can say IOException IS-A Exception and so, it will always be catched within the Exception block and the IOException block will be unreachable.
Real Life Example
Let's say, you're at a store and have to choose pants. The seller tells you that you have to try the pants from the largest ones to the smallest ones and if you find one that you can wear (even if it is not your size) you must take it.
You'll find yourself buying pants too large for your size and you'll not have the chance to find the pants that fits you.
You go to another store : there, you have the exact opposite happening. You can choose your pants from smallest to largest and if you find one you can wear, you must take it.
You'll find yourself buying pants at your exact size.
That's a little analogy, a bit odd but it speaks for itself.
Since Java 7 : multi-catch
Since Java 7, you have the option to include all the types of Exceptions possibly thrown by your try block inside one and only catch block.
WARNING : You also have to respect the hierarchy, but this time, from left to right.
In your case, it would be
try{
//doStuff
}catch(IOException | Exception e){
e.printStackTrace();
}
The following example, which is valid in Java SE 7 and later,
eliminates the duplicated code:
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}
The catch clause specifies the types of exceptions that the block can
handle, and each exception type is separated with a vertical bar (|).
First case:
catch (IOException e) { // A specific Exception
e.printStackTrace();
}
catch (Exception e) { // If there's any other exception, move here
e.printStackTrace();
}
As you can see, first IOException is catched. This means we are aiming at just one specific exception. Then in second catch, we aim for any other Exceptions other than IOException. Hence its logical.
In second:
catch (Exception e) { // Move here no matter whatever exception
e.printStackTrace();
}
catch (IOException e) { // The block above already handles *Every exception, hence this won't be reached.
e.printStackTrace();
}
We catched any exception (whether its IOException or some other Exception), right in the first block. Hence second block will not be reached because everything is already included in first block.
In other words, in first case, we aim at some specific exception, than at any other exceptions. While in second case, we first aim at all/any Exception, than at a specific exception. And since we already dealt will all exceptions, having a specific exception later won't make any logical sense.
Why does throw outerE; generate a compilation error? I know that throw e; should not generate a compiler error because of the precise rethrow feature.
They're the same Exception object, but one is scoped inside the catch block only and one is scoped outside the try-catch block.
Shouldn't neither of these generate a compiler error? Or, at least, both behave the same way?
static void preciseRethrowTest()
{
Exception outerE;
try
{
}
catch (Exception e)
{
outerE = e;
// Compilation error here. Unhandled exception type Exception
// throw outerE;
throw e; // No compiler error
}
}
I'm using Java 1.8.0_51. (Precise rethrow is introduced in Java 7)
Your method has no throws declarations.
The compiler is now smart enough to determine that your try block cannot throw any checked exceptions. Therefore, any exceptions caught and bound to the Exception parameter in your catch block must be unchecked. Since they are unchecked, you can rethrow them at your leisure (and they won't require a throws declaration).
Here, you are attempting to reassign
outerE = e;
// Compilation error here. Unhandled exception type Exception
// throw outerE;
and rethrow the exception through a different variable. The compiler doesn't go that far to figure out what the value in outerE is. It can be the exception in you caught or it can be something else. The compiler play it safe and prevents you from doing it.
Consider code like
if (Math.random() < 0.5)
outerE = e;
else
outerE = new IOException("nope");
throw outerE;
There's no way for the compiler to know whether the Exception value stored in outerE is the unchecked exception you caught or some other, potentially checked, exception you assigned from somewhere else.
The problem is that the catch block cannot be reached by checked exceptions; the compiler is smart enough to realize this.
Consider this:
public class RethrowTest {
static void preciseRethrowTest() {
Exception outerE;
try {
throw new Exception();
} catch (Exception e) {
outerE = e;
// Compilation error here. Unhandled exception type Exception
// throw outerE;
throw e; // Now a compiler error *is* generated.
}
}
}
This does throw a compiler error, because the code can be reached by a checked exception now.
I'm creating a function that will do a socket accept and return 3 vales
0=really bad error happen exit thread
1=ok talk to the connection
=something happen, do another accept (time out).
I see the IOException has a GetCause meths that returns a throwable object.
this throwable object has a get cause method that returns a throwable, which has a getcuase method returning a throwable, seems like this would go on forever, keep getting another throwable object.
How can I get the reason the exception ant off?????
I could use get reason and a bunch of string compares, but this does not seem to reliable.
Ted
int GetClient()
{
try {
server.setSoTimeout(5*1);
connection=server.accept();
}
catch(IOException ec)
{
System.out.println(Thread.currentThread()+":"+ec.getMessage());
return 2; // for time out or something where we can try again
// return a zero saying we must stop erra o bad
}
return 1;
}
accept()
throws a variety of exceptions.
SocketTimeoutException extends IOException but you can 'catch' it before catching the general IOException. This will allow you to return the value suggesting you can try again.
Does this cover your 3 cases, Ok, IOException and Timeout?
If you're only interested in timeout exceptions then catch those exceptions separately. Most IO methods can potentially throw an IOException, but there are many different subclasses of IOException (which themselves have further subclasses) that you can catch and deal with separately.
eg.
try {
conn = server.accept();
} catch (SocketTimeoutException e) {
return 2;
} catch (IOException e) {
// socket exception will not be recaught
// even if return statement wasn't used
return 0;
}
return 1;
The getCause method is provided as when exceptions are created they can be created with string message, but also the exception that may have caused this exception to be thrown. Thus allowing catchers of the exception to see the full detail of what caused the exception.
eg.
public double addNumbers(String a, String b) {
try {
double i = Double.parseDouble(a);
double j = Double.parseDouble(b);
return i + j;
} catch (NullPointerException cause) {
throw new IllegalArgumentException(
"Arguments aren't allowed to be null", cause);
} catch (NumberFormatException cause) {
throw new IllegalArgumentException(
"One or more arguments weren't numbers", cause);
}
}
The above case is a little obtuse, but it demonstrates the principal that some exception may be caught (that maybe it might try to be recovered from) and then a new exception thrown with the original exception as the cause. Having a getCause method allows the caller to immediately see that the IllegalArgumentException was originally thrown in the addNumbers method (and that this is where the problem in the user code base is). However, by looking at the cause they will be able to see a more detailed message about by the argument was illegal (NumberFormatException includes the string that was trying to be parsed).