Why does the following code not execute,
try {
System.out.println("abc");
}
catch(FileNotFoundException e) {
e.getMessage();
}
but why does this execute
try {
System.out.println("abc");
}
catch(Exception e) {
e.getMessage();
}
A print statement will not throw a FileNotFoundException error whereas Exception will catch any generic exception in Java.
That is because FileNotFoundException is a so-called Checked Exception.
It can only occur if System.out.println explicitly throws it.
The Compiler can detect that & will flag it.
On the other hand, Exception could be masking a RuntimeException or Subclass thereof.
(for example NullPointerException, which need not be explicitly declared)
The Compiler cannot detect that, and therefore must allow subclasses of RuntimeException, RuntimeException itself, Exception and Throwable.
Related
Java allows me to compile the following code without any issues:
public class Test {
public static void main(String[] args){
try {
throw new RuntimeException();
} catch (Exception e) {
throw e;
}
}
}
Even though java.lang.Exception is a checked exception. Meaning that I am rethrowing unchecked exception as checked and get away with that.
Most likely Java compiler is able to figure out that no checked exception is thrown in the try block, but I can't find the section in the specification that backups that.
Can one rely on this behavior and starting from which JDK version?
Update:
This class doesn't compile with Java 1.6.0_38 with the following message:
Test.java:6: unreported exception java.lang.Exception; must be caught or declared to be thrown
throw e;
^
1 error
It looks like that this is one of the effects of the enhancement in Java 7: Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking. See section "Rethrowing Exceptions with More Inclusive Type Checking."
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.
Please note, that the following will not compile though even in Java 7 and above:
public class Test {
public static void main(String[] args){
try {
throw new RuntimeException();
} catch (Exception e) {
Exception e1 = e;
throw e1;
}
}
}
Because:
This analysis is disabled if the catch parameter is assigned to another value in the catch block.
The part of the Java Language Specification that governs this can be found in JLS 11.2.2
11.2.2. Exception Analysis of Statements
...
A throw statement whose thrown expression is a final or effectively
final exception parameter of a catch clause C can throw an exception
class E iff:
E is an exception class that the try block of the try statement which declares C can throw; and
E is assignment compatible with any of C's catchable exception classes; and
E is not assignment compatible with any of the catchable exception classes of the catch clauses declared to the left of C in the same try
statement.
When E is RuntimeException 1) E can be thrown in the try block, 2) the catch clause can catch it, and 3) there are no catch clauses "to the left". Therefore the throw in the catch clause can throw RuntimeException.
On the other hand, E is Exception, E cannot be thrown in the try block. Therefore the throw in the catch clause cannot throw Exception.
Java docs explains clearly about object coherency while dealing with type-casting,return type of Over-riding method and throwing and catching Exceptions. But now i am little confused with Exceptions, What is the hidden concept behind this code..
void getNames() throws SQLClientInfoException { /*throws Subclass object to caller*/
try{
// throwing Subclass object to catch block but up-casting to Exception
throw new SQLClientInfoException();
} catch (Exception e) {
throw e; /* re-throwing throwing as Exception
}
}
Its a feature of programming language introduced in Java SE 7 - Use more precise re-throw in exceptions.
The Java SE 7 compiler performs more precise analysis of re-thrown exceptions than earlier releases of Java. This enables to specify more specific exception types in the throws clause of a method declaration.
Prior to Java 7:
void aMethod() throws CustomDbException {
try {
// code that throws SQLException
}
catch(SQLException ex) {
throw new CustomDbException();
}
}
Re-throwing an exception in the catch block need not indicate the
actual exceptions possible from the try block.
The type of exception thrown could not be changed without changing
the method signature.
In Java 7 or higher:
void aMethod() throws IOException {
try {
Files.copy(srcePath, trgtPath); // throws IOException
}
catch(Exception ex) {
throw ex;
}
}
The above code is legal in Java 7.
If an exception of some type is thrown in the try clause and is not assigned an exception variable in the catch clause, the compiler will copy over the checked exception type that can be thrown from the try block. (It is as if throwing all the exceptions possible from the try block provided that the exception variable is not reassigned).
The compiler knows that the only possible exception type is an IOException (because that is what the Files.copy() can throw).
Also, see this article at Oracle's website: Rethrowing Exceptions with More Inclusive Type Checking.
Because SQLClientInfoException is a subclass of "java.lang.Exception", it is caught by catch block when SQLClientInfoException is thrown
"e" variable in the catch block refers to SQLClientInfoException.
If you run following code then it will compile and run successfully,
public class Example {
public static void main(String[] args) {
// insert code here
try {
new Example().go();
// throw new OutOfMemoryError();
} catch (Error e) {
System.out.println(e);
}
}
void go() {
go();
}
}
With following output :
java.lang.StackOverflowError
So my question is "Can we catch an Error"..??
Answer to your question is yes, you can catch error in java. And your code is almost correct. Your method go() calls itself infinitely and therefore causes StackOverflowError that is caught in your catch block and printed by System.out.println()
Yes, you can catch an Error, but you are advised not to do it, since Errors indicate serious problems that a reasonable application should not try to catch. (as stated in the Javadoc of Error)
Yes, we can catch an error.
The Throwable class is the superclass of all errors and exceptions in the Java language. Only objects that are instances of this class (or one of its subclasses) are thrown by the Java Virtual Machine or can be thrown by the throw statement.
Similarly, only this class or one of its subclasses can be the argument type in a catch clause. For the purpose of compile-time checking of exceptions, Throwable and any subclass of Throwable that is not also a subclass of either RuntimeException or Error are regarded as checked exceptions.
try {
while(true) {
}
} catch (Throwable e) {
// TODO: handle exception
System.out.println(e);
}
Note that there's a difference between StackOverflowException and StackOverflowError, since you have an error, it's a serious indication that you should never try to catch it.
Just don't do infinite things in your code, when this error happens, no stack space is available, how would you want to proceed?
StackOverFlowError indicates that you have severe problems, it's a bad idea to catch this error, instead, try to understand what problems you have in your code and fix them.
I am confused about the behaviour of the CustomExceptions in below program.If Line2 is commented and Line1 is not then program works well,but if Line1 is commented and Line2 is not then compile time error comes as "Unreachable catch block for CustomChecked.This exception is never thrown from the try statement body" for Line3.Please help me why this comple time exception comes only for the unChecked Exception?.
try
{
if(true)
{
throw new CustomChecked("Checked Exception");// Line1
// throw new CustomUnChecked("Un-Checked Exception");// Line2
}
}
catch(CustomChecked ex) //Line3
{
System.out.println(ex.getMessage());
}
catch(CustomUnChecked ex)
{
System.out.println(ex.getMessage());
}
Exceptions :
class CustomChecked extends Exception
{
public CustomChecked(String msg) {
super(msg);
}
}
class CustomUnChecked extends RuntimeException
{
public CustomUnChecked(String msg) {
super(msg);
}
}
CustomUnChecked is a RuntimeException which is unchecked meaning that the complier doesn't check who can/do throw that exception. Compiler assumes that every object/method/code block can throw any type of RuntimeException and so that you can always check for this type of exceptions in your check statements.
On the other hand CustomChecked is checked, meaning that the compiler checks for all methods and code blocks that can throw it. So you can only catch the checked exception if you know (at a complie time) that you invoke a method/code that throws the exception inside the try block.
So to sum up - your compilator informs you, that the catch you have in line 3 is not needed (and so should be removed), because there is no way that somebody will throw CustomCheckedException inside the try statement. As CustomUnCheckedException is not checked by compiler (it is runtime, assumed to be thrown unexpected anywere), the check statement for it can stay.
The part of the Java Spec that is applicable here is 11.2.3. It reads
It is a compile-time error if a catch clause can catch checked exception class E1 and it is not the case that the try block corresponding to the catch clause can throw a checked exception class that is a subclass or superclass of E1, unless E1 is Exception or a superclass of Exception.
Notice that this clause is restricted to 'checked' exceptions. Unchecked exceptions, by definition of being 'unchecked' do not have these checks applied to them. Hence the difference in behavior that you are seeing.
The compiler does not check if you catch RuntimeExceptions, but it does check that you catch Exceptions. Thats why you get an error if you try to catch a non-existant checked exception (if its not in the throws clause, it shouldnt exist, since its a checked exception), and no error if you are catching a RuntimeException (which can happen even through you didnt put it in the throws clause, a NullPointerException for example).
So, in short, CheckedExceptions MUST be declared in the throws clause and MUST be catched.
Unchecked exceptions CAN be catched, but the compiler has no way of knowing the if code throws an unchecked exception, so it wont give you an error if you check on it or not.
I can't seem to find a way to fix this. I have a class called CardException which extends Exception. The only code it has is:
public class CardException extends Exception{
String erro;
public CartaoException(String erro){
this.erro = erro;
}
}
Now I have another class with a method in which I want to throw an Exception if the condition is false:
public void changePin(int pin, int newPin){
try{
if(pin == getPin()){
setPin(newPin);
}
} catch (CardException e){
System.out.println(e.getMessage());
}
}
but I'm getting an error at "catch (CardException e)" saying:
"Unreachable catch block for CardException. This exception is never thrown from the try statement body" and I have no idea why.
The point is to create a class called CardException of Exception type, with a constructor that receives an error message as argument. Then, on my other class, I need to create that method changePin which receives the old pin and a new pin and, if the old pin doesn't match the one already saved, it has to throw and exception with a message: "Invalid pin".
Java compiler is intelligent enough to determine whether the statements inside try blocks are prone to a checked exception or not. As no statement in your try block seems to cause CardException, hence compiler complains.
Just for the sake of testing, if you add throws clause with CardException to either of your getPin/setPin method, then compiler will not complain as those methods can throw the exception in catch block.
Since CardException extends Exception, not RuntimeException, it is considered a checked exception. What that means is that all methods from which the exception is thrown must declare the exception in their throws declaration clause.
Because of this requirement Java compilers can check if a code block throws a particular checked exception or not:
If there is a throws block inside the code body that throws this exception or one of its subclasses, the catch is valid
If any of the functions called inside the code body is declared as throwing the exception or one of its subclasses, the catch is valid
Otherwise, the catch is invalid, and the compiler issues an error.
You would need to catch this exception if getPin or setPin threw it. In this case, however, the functions would need to add a throws CardException to their declarations.