I have some few doubts on exceptions.
Can anyone tell me why java doesnt allow us to create Checked Exception in a Subclass while it allows Unchecked exception in a subclass
Below exampple throws Compile time error when I use 'throws IOException' , BUT it doesnt throw any error when I use 'throws ArithmeticException' in a subclass.. I just wanna know the actual reason behind it, so can you please?
Here is code (you will get compile time error)
package com.exception.test;
import java.io.IOException;
public class Parent {
void msg() {
System.out.println("Parent...");
}
public static void main(String[] args) {
Parent parent = new Child();
parent.msg();
}
}
class Child extends Parent {
void msg() throws IOException {
System.out.println("Child...");
}
}
//using unCheckedException
package com.exception.test;
import java.io.IOException;
public class Parent {
void msg() {
System.out.println("Parent...");
}
public static void main(String[] args) {
Parent parent = new Child();
parent.msg();
}
}
class Child extends Parent {
void msg() throws ArithmeticException {
System.out.println("Child...");
}
}
If a subclass method declares it can throw a checked exception that the parent doesn't, it breaks the Liskov substitution principle, which is one of the corner stones of object oriented programming.
Consider this bit of code, with Child.msg declared to throw a checked exception:
void doMsg(Parent p) {
p.msg();
}
The program semantics break if you pass in a child object because the checked exception is now neither being caught nor thrown: the exception is no longer "checked."
Since unchecked exceptions can be thrown everywhere, declaring to throw one serves no other purpose than documentation. Therefore it can be allowed safely.
The msg() method in your parent class can throw any unchecked exception it likes. Hence, if you explicitly declare that your child throws an unchecked exception, you're not actually altering the contract. Your child method may throw an ArithmeticException, but so might your parent method.
Checked exception can be narrowed down while overriding, but not can't be broaden. Unchecked exception need not be caught by the overridden methods
From the java specs
The checked exception classes named in the throws clause are part of
the contract between the implementor and user of the method or
constructor. The throws clause of an overriding method may not specify
that this method will result in throwing any checked exception which
the overridden method is not permitted, by its throws clause, to
throw.
Unfortunately, you have hit yet another pitfall of Java's misfeature known as Checked Exceptions. The error you are receiving is an actual problem that all Java professionals face: you are implementing a method with some code that happens to throw a checked exception not declared by the superclass method. The declared checked exceptions are a part of the Java method signature; you can reduce the list in a subclass, but you cannot expand it.
If this is more that just a "why" question, and you need a workaround, the standard idiom is
try {
...code that throws the checked exception...
} catch (TheCheckedException e) { throw new RuntimeException(e); }
This is called exception wrapping. If you have more than one or two undeclared checked exceptions, you can also use the opposite idiom, ensuring that all declared exceptions propagate transparently and all undeclared ones get wrapped:
try {
...code that throws various checked exceptions...
}
catch (DeclaredEx1 | DeclaredEx2 | RuntimeException e) { throw e;}
catch (Exception e) { throw new RuntimeException(e); }
Related
I understand that catching a checked exception that is never thrown in the corresponding try block is invalid. Because the compiler itself would have forced the programmer to handle the exception if it was to occur.
For example, this code snippet -
try
{
}
catch(IOException e)
{
}
is invalid.
But why doesn't the compiler work the same way for the method that throws a checked exception that has never been thrown in the body of the method?
For example, this code snippet -
void test() throws IOException
{
}
is surprisingly valid.
Please explain the reason behind it. TIA.
Because you might want to allow subclasses to throw this exception.
public abstract class Parent {
public void doStuff() {}
}
public class Child {
// this is illegal, because you throw more exceptions than the overridden method
public void doStuff() throws IOException {}
}
This is even more intuitive for interfaces, the (non-default) methods of which will never throw an exception but can declare it.
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.
This tells you all these are valid:
try { }
catch(Exception e){}
--
try{ }
catch(NullPointerException e) {}
--
try{ }
catch(ArrayIndexOutOfBoundsException e) {}
--
try{ }
catch(RuntimeException e) {}
--
try{ }
catch(Error e) {}
--
try{ }
catch(Throwable e){ }
It's not related to a void block. It's related to an impossible path to your checked subclass of Exception.
What happens with subclasses of Exception? For example IOexception: Those are unreachable catch blocks. Nothing in the try block can lead to that exception, so the compiler just tells you: this block would never be executed, as it would never catch that subException.
The difference with throws: The concept of unreachable code doesn't exist in this context. The possibility of a method throwing an exception doesn't end in the deffinition of the method. For example:
abstract void readFile(String path) throws IOException;
This method doesn't even have a block, as it's an abstract method. It's easy to guess that this line won't ever throw any IOException. But it defines a behaviour for the extensions that will implement it. In order to override it, your method must throw the IOException.
In the same way, if someone overrides your test method:
#Override
void test() throws IOException
{
readFile(file);
}
It's not impossible to happen, in contrary to your first try-catch block.
Java follows the rule "handle or declare".
If there is a checked exception declared in your code, you must handle it (in a try/catch block) or declare it (adding 'throws' on method signature).
When you say your method may throw an exception, everyone using your method must handle or declare that exception. If you handle it, you are making your code capable of recovering. If you declare it, you are passing the problem to the caller.
The compiler is fine if you declare 'throws', he knows what to do when your method will be called.
If you declare an exception that is not actually there, you are making users of your code aware that, in a future release, you may add that exception. Users will be prepared for the day you will add that exception.
Specifying says that method can throw an exception or can not throw. But compiler don't check it, because he can't, actually. So try block only check specifying. The
point is compiler don't see deference between actual calling exception and method's specifying. If you call test() in try block, it'll valid. Sorry for my English)
I have a hard time to understand why the following code compiles, while it is not a subclass of exception:
class Test
{
public void run() throws IOException
{
System.out.println("Test");
}
}
class SubTest extends Test
{
//not a subclass of IOException, still compiles
public void run() throws RuntimeException
{
System.out.println("Test from sub");
}
}
class Sub2Test extends Test
{
//not a subclass of IOException, does not compile
public void run() throws Exception
{
System.out.println("Test from sub");
}
}
I understand RuntimeException is an unchecked exception, but I thought the rule was that it must be a subclass of the parent exception?
Imagine there is a caller which calls Test#run. In the declaration of Test#run, it says it might throw IOException, so the caller knows it can catch and handle it:
Test test = // it could be instance of SubTest of Sub2Test
try {
test.run();
} catch (IOException e) {
}
Then it's ok if SubTest does not throw IOException, the caller will not miss anything.
But if you throw some checked Exception like Sub2Test, since the caller does not know it until runtime, the called is not able to catch and handle it. So it should not be compiled.
"I understand RuntimeException is an unchecked exception, but I thought the rule was that it must be a subclass of the parent exception?"
That is the general rule, as specified in the JLS in section §11.2. Compile-Time Checking of Exceptions, which states (emphasis mine)
The throws clause of an overriding method may not specify that this method will result in throwing any checked exception which the overridden method is not permitted, by its throws clause, to throw (§8.4.8.3).
But that only applies to checked exceptions, and it also explicitly states that
The unchecked exception classes (§11.1.1) are exempted from compile-time checking.
So the compiler is going to ignore the fact that RuntimeException isn't a subclass of IOException.
If I have a class called Boat, and if I write :
class Boat throws Exception
Inside my class I am using try catch block to catch ArithmeticException for instance.
What benefit there is to declare an exception versus not declaring an exception?
A class does not throw exceptions. Only methods do.
For some exceptions (checked exceptions that may occur in your code and that you do not catch) the compiler forces you to declare them.
You never have to declare RuntimeExceptions (such as ArithmeticException), but you can. This serves as documentation.
You can declare checked exceptions that your code does not throw. This makes it future-proof if you might later want to throw them, and also allows for subclasses to do such.
When declaring exceptions, you can go broad/generic (throws Exception or even throws Throwable), but it is generally better to be more specific. That gives the people using your code a better idea of what to expect. The whole purpose of having these many specific Exception classes is to make it easier to handle exceptions appropriately (and have the compiler enforce the fact that someone at least thought about doing that).
First classes won't throw Exception, only methods will throw
check this Example
class A
{
public A() throws Exception
{
int k=5/0;
}
}
public class B
{
public static void main(String[] args)
{
A a=new A();
}
}
When you run the above you'll get compile time error saying
Unhandled exception type Exception
because when ever methods throws exception , they are expected to handle by calling object, it is just like saying 'Hey somebody handle Exception', so the method calling it should handle the Exception , if they don't it will be a compile time error.
For the smooth execution of program, Exception thrown by method should be handle by calling method. Here is how you need to handle.
class A
{
public A() throws Exception
{
int k=5/0;
}
}
public class B
{
public static void main(String[] args)
{
try{
A a=new A();
}
catch(Exception e)
{
System.out.println("caught "+e);
}
}
}
Declaring Exception will allow your program to compile if any Exception can be determined by the compiler to "escape". It's primary purpose, though, is to document to the user of your method (and to their compilers) that it may throw an Exception.
As such, declaring Exception, vs declaring a more specific exception cause, is nullifying the benefits of the scheme -- cheating.
If you write something like that,
double x = 1/0;
System.out.print("hey");
it will give you an exception and your code is going to stop, will not print hey. But if you encapsulate it with try/catch, it will not stop.
try{
double x = 1/0;
}catch(ArithmeticException){}
System.out.print("hey");
This will print hey.
A java book used by one of the students that I tutor contains the following (Blue Pelican Java version 3.0.5b Charles Cook):
If you have a method that throws an IOException up to the next level in the calling chain, we should be aware that in addition to IOException being thrown to the next level, all its subclasses are also thrown to the next level in the chain.
This seems obviously false, but is it correct? A version of this statement was posed on the student's exam, and was supposed to be true.
Also, the following code seems to be a counterexample to the claim:
public class ExceptionsTester {
public static void main(String[] args) {
try {
throw new IOException();
} catch (FileNotFoundException e) {
System.out.println("Subclasses thrown");
} catch (IOException e) {
System.out.println("Subclasses not thrown");
}
}
}
Did the book mean: 'If a method declares it throws Exception, then all subclasses of Exception can be thrown by it'? Because that's true in Java, but it doesn't tell you anything about the behaviour of catching exceptions and their subclasses (as the other answer suggests)
It doesn't make any sense on multiple levels and as worded is completely false.
Throwing an IOException does precisely that, throws an IOException.
Subclasses of IOException won't be caught, because they're not thrown.
Catching a superclass of an exception will catch the exception (although in this case it's java.lang.Exception, of course).
I'm not convinced the author is stating that if (say) an IOException is thrown then all IOException subclasses are also thrown. Based on reading the previous sections I think he's trying to make the point that if something declares it can throw an IOException it also means that IOException subclasses can be thrown.
It's worded horribly, but I have a difficult time believing the author thinks IOException subclasses are thrown when an IOException is thrown–he correctly points out that subclasses must be caught before their less-specific superclasses immediately prior. I find it more likely there was either an editing issue or it was just poorly stated.
Well this is not correct. First of all this is a static method and static methods dont get passed to the sub classed. Second this one does not throw an exception. It only handles it. By throwing an exeption I think the book author meant was declaring the method with a throws keyword.
for example
class A {
void x() throws IOException {}
}
if :
class B extends A {
#overries
void x() {}
}
Even though the overriden method in B does not explicity throw it, anyone who uses the method in B must handle the IOException.
A a = new B();
a.x();
Compiler will complain. You must use
A a = new B();
try {
a.x();
} catch (Exception e) {}
So the bottomline is the author is correct in a way.
when coding. try to solve the puzzle:
how to design the class/methods when InputStreamDigestComputor throw IOException?
It seems we can't use this degisn structure due to the template method throw exception but overrided method not throw it. but if change the overrided method to throw it, will cause other subclass both throw it.
So can any good suggestion for this case?
abstract class DigestComputor{
String compute(DigestAlgorithm algorithm){
MessageDigest instance;
try {
instance = MessageDigest.getInstance(algorithm.toString());
updateMessageDigest(instance);
return hex(instance.digest());
} catch (NoSuchAlgorithmException e) {
LOG.error(e.getMessage(), e);
throw new UnsupportedOperationException(e.getMessage(), e);
}
}
abstract void updateMessageDigest(MessageDigest instance);
}
class ByteBufferDigestComputor extends DigestComputor{
private final ByteBuffer byteBuffer;
public ByteBufferDigestComputor(ByteBuffer byteBuffer) {
super();
this.byteBuffer = byteBuffer;
}
#Override
void updateMessageDigest(MessageDigest instance) {
instance.update(byteBuffer);
}
}
class InputStreamDigestComputor extends DigestComputor{
// this place has error. due to exception. if I change the overrided method to throw it. evey caller will handle the exception. but
#Override
void updateMessageDigest(MessageDigest instance) {
throw new IOException();
}
}
In this case, your super class is not meant to throw an exception.
This is a case where your subclass is thus throwing an exception which is not expected by the overlying software architecture. Thus you can :
update all subclasses to throw exceptions.
wrap the entire Digestor class framework in a new class system.
(simplest) maintain the current code and simply wrap any exceptions you wish to throw in a RuntimeException.
RuntimeExceptions are the idiomatic way to throw exceptions in java which are not checked by the compiler or by method signatures, which occur somewhat unexpectedly.
Your requirements are schizophrenic.
You've got to decide whether the DigestComputor.updateMessageDigest method can, or can not throw IOException. If you want that to be possible, then you must add it to the signature in the base class. That is the only way to force the caller to do something about an IOException. But the downside is that you also force callers of the other subclasses to handle the IOException ... which won't occur.
You cannot create a method override that throws checked exceptions that the overridden method does not. That would break subtype substitutability, and Java doesn't allow it.
It it like a fork in the road. You have to decide to go one way or the other. You can't go both ways at the same time.
However there is a compromise (sort of):
public abstract class Base {
public abstract void method() throws IOException;
}
public class A extends Base {
public void method() throws IOException {
//
}
}
public class B extends Base {
public void method() { // Doesn't throw!!!
//
}
}
Now, if the caller knows that it has an instance of B it can do something like this:
Base base = ...
B b = (B) base;
b.method(); // No need to catch or propagate IOException
(IIRC, the ability to do this ... i.e. to reduce the exceptions thrown in an overriding method ... was added in Java 1.5.)
As someone else suggested, the simplest thing to do would be to simple wrap the real exception in a runtime exception. As a result, you don't have to declare the exception in your throws clause. If you're ambitious enough you can make your own subclass of RuntimeException and catch it at a higher level (this is what hibernate does, it catches all SQLExceptions thrown and wraps them in some subclass of DataAccessException which is a runtime exception).