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.
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 class like this:
public class FooBar
{
public String foo() throws Exception {
return "";
}
public String bar() throws Exception {
throw new BazException();
}
}
Inside a eclipse, I get a warning on method foo stating:
The declared exception Exception is not actually thrown by the method foo() from type FooBar
See below:
Question: Is it possible to configure a silmiar warning for method bar? Method bar doesn't throw the most specific exception that it could.
I am using:
Eclipse Oxygen Release (4.7.0)
Java 8
Your post is raising two distinct issues. First issue:
Is it possible to configure a similar warning for method bar?
Yes, though no configuration is needed. If a method declares that it throws some sub-type of Exception but actually doesn't, then a similar warning to the one you report will be displayed in Eclipse. There is nothing special about an exception of type Exception with regard to that warning.
In your code just change method foo() to throw BazException instead of
Exception to see that:
Second issue:
Method bar doesn't throw the most specific exception that it could.
That is true, but is an issue distinct from getting a message about an exception not being thrown at all. There is no way to configure Eclipse to throw a message like "The method {m} does not throw the most specific exception that it could" since there is no message along those lines in Eclipse's list of compiler Errors/Warnings.
Besides, the wording of such a message could get tricky and convoluted in a complex method that threw multiple exceptions. Perhaps a code analyzer tool such as PMD could identify offending methods for you.
No, Eclipse only displays a warning in the first case, because throwing an exception that can never occur is a code smell, whereas throwing a more general exception is not a code smell.
Throwing an exception that can never occur
This forces the caller unnecessarily to handle the exception, for example:
public class Foo {
public static void main(String[] args) {
Foo foo = new Foo();
try {
System.out.println(foo.foo());
} catch (IOException e) {
// unreachable code
}
}
public String foo() throws IOException {
return "";
}
}
For simplified exception handling, some people prefer to add generally the throws Exception or the throws Throwable declaration to almost any method. Therefore, the warning can be configured to ignore these special cases: in Project > Properties: Java Compiler > Errors/Warnings, section Unnecessary code > Unnecessary declaration of thrown exception uncheck Ignore 'Exception' and ' Throwable'.
Note, if an interface method has a throws declaration, the implementing class does not need to have also a throws declaration:
public class Foo implements IFoo {
public String foo() {
return "";
}
}
interface IFoo {
String foo() throws IOException;
}
Throwing a more general exception
A more general exception is useful if you want to hide details from the caller (for the same reasons you should prefer List list = new ArrayList(); over ArrayList list = new ArrayList(); in most cases). It gives you more flexibility to change the code of the method without having to modify the code of the caller.
However, maybe you can create problems markes with SpotBugs, Checkstyle, PMD or similar plug-ins for that. If at all, I would recommend to do this only for private methods.
So picture the following scenario. I have two sets of classes and interfaces. ClassA, ClassB, ClassAInterface, and ClassBInterface. ClassA uses ClassB in several of its methods. These methods from ClassB occasionally throw exceptions.
public class ClassA implements ClassAInterface {
public void example() {
ClassB test = new ClassB();
ClassB.exampleTest();
//more code using ClassB
}
}
public class ClassB implements ClassBInterface {
public void exampleTest() throws ExampleException() {
boolean tru = false;
if (tru) {
throw new ExampleException();
}
}
}
So the problem that I'm having is that I'm getting an Unhandled Exception type ExampleException() error in the ClassA.example() method. Why does this happen? I want the ClassB method to throw the exception in specific cases, and signify that it sometimes throws exceptions with throws ExampleException(), so why does ClassA not compile. To solve it, I can't add a throws statement onto ClassA.example() because it would violate ClassAInterface. And if I just wrap ClassB.exampleTest() in a try catch statement, much of the rest of ClassA.example() would throw errors because ClassB signifies something is wrong and you should throw an exception at that point, which is the entire point of throwing an exception`. So I'm not sure why this is happening or how to solve it.
Why does the code refuse to compile?
It's quite normal. As you said, B.exampleTest() sometimes throws an exception. A.example() calls B.exampleTest() and does not catch any exception. So, even if the exception doesn't always happen, it happens sometimes. And when it happens the exception is also thrown by A.example(). So it has to be declared or caught. Just like B.exampleTest() sometimes throws an exception, A.example() also sometimes throws the same exception.
Now, what to do? You have 3 choices:
declare that the exception is thrown: the caller of A.example() will then have to decide what to do in that case.
catch it inside A.example(), and deal with it somehow.
catch it, wrap it inside a runtime exception (which doesn't have to be declared in the throws clause), and throw this runtime exception. The caller will have to deal with this runtime exception, but won't have any hint from the compiler that an exception can be thrown.
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); }
Suppose I have interface I and two classes A and B that implement it.
The implementation of method f of this interface in A throws one set of exceptions and the implementation in B throws another set. The only common ancestor of these exceptions is java.lang.Exception. Is it reasonable to declare f throwing java.lang.Exception in this case? Any other alternatives?
The reason why I am asking is that on the one hand java.lang.Exception seems too general to me and one the other hand listing all exceptions seems impractical considering possible other implementations.
Example:
interface I {
void f() throws Exception;
}
class A implements I {
public void f() throws IOException {}
}
class B implements I {
public void f() throws InterruptedException {}
}
The reason for using an interface is to abstract away the implementation details.
By throwing these exceptions, you're exposing implementation details that probably should be abstracted away.
Perhaps it would be best to define a new exception. Then each implementation of f() would catch the exceptions it knows about and throw the new exception instead so you'd have:
interface I {
void f() throws MyException;
}
class A implements I {
public void f() throws MyException {
try {
...
} catch (IOException e) {
throw new MyException(e);
}
}
}
class B implements I {
public void f() throws MyException {
try {
...
} catch (InterruptedException e) {
throw new MyException(e);
}
}
}
By wrapping the implementation exception, you're still exposing it to the caller and that can bite you when you're calling remote methods. In those cases you need to do more work to return useful information in a generic way.
Edit
There seems to be a bit of a dispute going on about the correct approach.
When we call f(), we'll need code like:
I instanceOfI = getI();
try {
instanceOfI.f();
}
catch ( /* What should go here ? */ )
It comes down to what is a good Exception class to put in the catch block.
With OP's original code we could catch Exception and then maybe try to see which subclass we have, or not depending on requirements. Or we could individually catch each subclass but then we'd have to add catch blocks when new implementations throw different exceptions.
If we used Runtime exceptions it would come to much the same thing except that we could alternatively defer the exception handling to a caller method without even giving the possibility of exceptions any thought.
If we used my suggestion of using a new, wrapped exception then this means we have to catch MyException and then try to see what additional information is available. This essentially becomes very like just using an Exception, but requires extra work for the limited benefit of having a bespoke exception that can be tailored to the purpose.
This seems a bit backward. You should be throwing exceptions that are relevant and possibly specific to your interface, or not at all. Change the implementations to wrap a common Exception class (although not Exception itself). If you can't deal with this you may want to wrap the Exceptions in the implementations with a RuntimeException.
You could just declare the exceptions you throw
void f() throws IOException, InterruptedException;
If you use a decent IDE, it will correct this for you. I just throw the exception in the method, which the IDE gives the optionsto add to the method clause and its interface.