Java throw exception at class method - java

I have question on Java throw exception at class method definition:
public void someMethod () throws SomeException {
try{
...
}catch (SomeException e ){
....
}
}
When we declare throw SomeException at the method declaration, do we still have to try/catch in the body or, can we just use throw new SomeException like this:
public void someMethod () throws SomeException {
// do something
throw new SomeException() ;
}
what is the correct way to throw exception when we have throw Exception at the method declaration.

No, you do not need to catch the exception that you throw as long as you're not changing it or selectively throwing it only in some situations when the exception occurs. So this is often perfectly fine:
public void someMethod () throws SomeException {
// do something
throw new SomeException() ;
}
Although it's often good to give your SomeException class a constructor that takes a String parameter, and then pass that String to the super constructor to allow your exception to be able to pass more information through.

Your prototype public void someMethod () throws SomeException is mandating that someMethod will only throw exceptions of type SomeException. (Or any exception classes derived from SomeException).
Therefore you do not need to catch that particular exception in your function, but you will need to catch all others.

Related

Why must I catch exceptions when providing lambda argument?

Consider the following example:
public class LambdaArgsTest {
private static void display(Supplier<?> arg) {
try {
// this is the place where the Exception("wrong") might be thrown
// and it is in fact handled
System.out.println(arg.get());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
display(() -> {
if(/*some condition*/) {
// this statement will be rejected due to unhandled exception
throw new Exception("wrong");
}
return "abcde";
});
}
}
Here comes the question: the lambda argument in the above example is an object that'll be executed later inside the "display()" method. It is obviously not executed when passing the arguments to the "display()".
Why is it rejected by the compiler? I think it's quite reasonable to surround it by try...catch only when the lambda is actually called.
This is because of the signature of Supplier functional interface:
T get();
As you see, the method get is not declared to throw Exception (neither any other checked exception).
In Java, there are checked vs unchecked exceptions (unchecked exceptions are those which inherit from RuntimeException). Checked exceptions must be handled, either by catching them in a catch block, or by declaring that the method throws that exception.
If the signature of Supplier.get were:
T get() throws Exception:
The code would compile fine.
Try throwing RuntimeException instead of Exception and the code will compile fine.
EDIT: As per Peter Lawrey's suggestion in the comments, if you do need to throw a checked exception from within your lambda expression, you could use e.g. Callable, whose only one method's signature is as follows:
T call() throws Exception;
You'd just need to pass a Callable to your display method instead of a Supplier.

Why does this compile? Overriding method not a subclass of exception

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.

throwing Generic Exception in java

I have another challenging question from javaDeathMatch game;
In the code below we are asked what kind of problem the code below has.
please correct me if I am wrong;
compilation error : None; At compile time the erasure of type parameter has not still occurred and the dynamic binding has not been taken place, so the parameter passed to the method which is of type SQLException is thought of as Exception in the method 'pleaseThrow' and it(i mean Exception not SQLException) is cast to Runtime Exception in the method with no error. The only error is that we don't have a proper catch clause to catch the exception.
public class Exption<T extends Exception> {
public static void main(String[] args) {
try {
new Exption<RuntimeException>().pleaseThrow(new SQLException());
}catch (final SQLException ex){
ex.printStackTrace();
}
}
private void pleaseThrow(final Exception t) throws T{
throw (T)t;
}
}
if we replace the catch clause with this:
catch(final RuntimeException e){
e.printStackTrace();
System.err.println("caught");
}
the exception will be caught but the System.err.println("caught") will never be printed!!! What is the problem????
This is due to type erasure. In java after compilation, every generic information is lost (there is something left, which is not relevant to this though). That means that during compilation, the generic variable T is equal to RuntimeException. So your pleaseThrow code looks like this:
private void pleaseThrow(final Exception t) throws RuntimeException{
throw (RuntimeException)t;
}
After compilation though, every generic parameter is erased to the base type. In your case, to Exception. Which leaves you with a method signature like this:
private void pleaseThrow(final Exception t) throws Exception{
throw (Exception)t;
}
Which finally is clear, why your catch block is never reached. You're trying to catch RuntimeExceptions but what you're actually throwing is a checked exception. Which then propagates upwards and is finally caught by the JVM.
Additional reading: Oracle Tutorial on type erasure
This code will fail to compile, because SQLException is a checked exception, and to catch a checked exception, it must be declared to be thrown by something inside of the try block. Here it is failing to compile on Ideone, for example, with the following message:
Main.java:7: error: exception SQLException is never thrown in body of corresponding try statement
}catch (final SQLException ex){
^
Note: Main.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
If you change the catch block so it catches RuntimeException, then the code will compile, but the exception will not be caught, because SQLException is not a subclass of RuntimeException.
There's a discussion of how the pleaseThrow method works here. That idiom is usually called "sneaky throws", and it lets the caller throw a checked exception as if it was an unchecked exception. For the difference between checked and unchecked exceptions, see the official tutorial or this Q&A and StackOverflow.
Let us take the first version of your code :
public class Exption<T extends Exception> {
public static void main(String[] args) {
try {
new Exption<RuntimeException>().pleaseThrow(new SQLException());
}catch (final SQLException ex){ // This is compilation error
ex.printStackTrace();
}
}
private void pleaseThrow(final Exception t) throws T{
throw (T)t;
}
}
How is compiler able to detect the error ?
It is not because of throw (T)t;. Infact , if you type cast to a type parameter , compiler ignores it and leaves it to JVM.
Then how does compiler able to generate error ?
It is because of this :
private void pleaseThrow(final Exception t) throws T
Notice the throws T . When you say new Exption<RuntimeException>() , compiler does not create any object. But it infers T during compilation. It comes under it powers.
Now , let us understand the whole picture of why error gets generated.
Compiler from private void pleaseThrow(final Exception t) throws T{ knows that you will throw RuntimeException.
According to rule of type casting , compiler checks both types if one is parent of other. If yes , it passes the code to JVM . Only JVM will then further check if one object can actually be type casted to other.
Similarly, compiler checks for throws and catch block if any is compatible or not. If more than one is compatible, it leaves the decision to JVM. Compiler checks for many other things too but let us focus on the main track.
In your example, One type is SqlException and other is RuntimeException. None is parent of other. Hence, compiler shows error.
Let us see few examples to clear it :
public class Exption<T extends Exception> {
public static void main(String[] args) {
try {
new Exption<RuntimeException>().pleaseThrow(new IllegalArgumentException());
}catch (final ClassCastException ex){
ex.printStackTrace();
System.out.println("done");
}
}
private void pleaseThrow(final Exception t) throws T{
throw (T)t;
}
}
In this example, Catch clause won't be called , however code compiles fine.
Since ClassCastException is a RuntimeException , Compiler compiles the code fine. RuntimeException is parent to ClassCastException.
But when compiler hands over code to JVM, JVM knows that exception object is of type IllegalArgumentException and hence will settle for a catch clause of IllegalArgumentException or it's super type. Here we have nothing like that. Hence, Catch clause won't be called as there is no match.
Take another example :
public class Exption<T extends Exception> {
public static void main(String[] args) {
try {
new Exption<RuntimeException>().pleaseThrow(new IllegalArgumentException());
}catch (final RuntimeException ex){
ex.printStackTrace();
System.out.println("done");
}
}
private void pleaseThrow(final Exception t) throws T{
throw (T)t;
}
}
This runs fine and catch block is called. JVM knows object type will be IllegalArgumentException and RuntimeException is super class , hence , it matches due to super class able to refer child class object.
Now, let us come back to your code.
You have only written only one catch block consisting of SqlException which is a checked exception and hence cannot be thrown from pleaseThrow() as it throws RuntimeException according to compiler.
So, this error gets generated :
Error:(9, 10) java: exception java.sql.SQLException is never thrown in body of corresponding try statement
As you know it is illegal in Java to have a catch block catching a checked expression never thrown.
Now , let us come to version 2 of your code :
public class Exption<T extends Exception> {
public static void main(String[] args) {
try {
new Exption<RuntimeException>().pleaseThrow(new SQLException());
}catch(final RuntimeException e){
e.printStackTrace();
System.err.println("caught");
}
}
private void pleaseThrow(final Exception t) throws T{
throw (T)t;
}
}
Now, things make sense as in catch block you have written RuntimeException.
Compiler sees that method throws RuntimeException and in catch block too we have runtime exception.
Now, let us look more closely. Compiler easily compiles this code and send it to JVM. But before that it does the type erasure.
Let us look what would type erasure would have done to our code :
[In actual code given to JVM is byte level code. The below example is to show what type erasure does to the code. Note that below code won't run properly in compiler if you try to compile as this code is after type erasure and few details have been lost which compiler needs. JVM however can run the equivalent byte code of this.]
public class Exption {
public static void main(String[] args) {
try {
new Exption().pleaseThrow(new SQLException());
}catch(final RuntimeException e){
e.printStackTrace();
System.err.println("caught");
}
}
private void pleaseThrow(final Exception t) throws java.lang.Exception {
throw (java.lang.Exception) t;
}
}
To understand how this code was reduced to , you need to read about type erasure. But trust me till here for time being.
Now, this code is very interesting piece of code.
On this code JVM directly operates. If you see JVM knows it method throws an Object of type SqlException type casted to Exception. It tries to find a match in catch blocks but no match. RunTimeException is not a super class of SqlException. Hence, no catch block is called.
Let us modify the code to understand it more.
public class Exption<T extends Exception> {
public static void main(String[] args) {
try {
new Exption<RuntimeException>().pleaseThrow(new SQLException());
}catch(final RuntimeException e){
e.printStackTrace();
System.err.println("caught");
}catch(Exception r){
System.out.println("done");
}
}
private void pleaseThrow(final Exception t) throws T{
throw (T)t;
}
}
This will output "done".

Using interface hides the exception thrown by implementation

Given the following code:
interface Provider
{
String getStuff();
}
class CustomProvider implements Provider
{
public String getStuff() throws RuntimeException
{
// possibly throwing an exception
return "some stuff";
}
}
class Main
{
public static void main(String[] args)
{
Main main = new Main();
main.test(new CustomProvider());
}
public void test(Provider provider)
{
provider.getStuff(); // we don't know that this can throw an exception!
}
}
In this particular case we know it but may not in another situation.
How can we protect from the situation where an implementation of an interface throws an unchecked exception but the client method doesn't know the specific implementation of the interface?
It seems that sometimes with unchecked exceptions you can actually never know if calling a method can throw an exception or not.
A solution could be change the signature of the method in the interface:
interface Provider
{
String getStuff() throws Exception;
}
This will ensure that the clients of that method will be advised that an exception can be thrown in all implementations. The problem with this is that maybe none of the implementations of the interface will actually throw an exception. Also putting a "throws Exception" in each method of an interface looks a bit weird.
It seems that sometimes with unchecked exceptions you can actually never know if calling a method can throw an exception or not.
The compiler doesn't check unchecked exceptions. You can document the constraints of the interface, but they won't be automatically validated by the compiler.
You suggest declaring that the method throws Exception. A more constrained approach would be to declare that the method throws some checked exception.
For example, you could declare specifically that your method may throw an I/O exception, as shown below. Callers then need only handle or throw IOException, rather than many more possible Exceptions.
interface Provider
{
String getStuff() throws IOException;
}
Another option is to declare an ad hoc exception type. This allows the interface to advertise an exception contract with callers, without limiting what kinds of exceptions implementations can encounter.
interface Provider
{
String getStuff() throws ProviderException;
}
class MyProvider implements Provider {
public String getStuff() throws ProviderException {
try {
...
} catch ( IOException e ) {
throw new ProviderException( e );
}
}
}
public class ProviderException extends Exception {
public ProviderException( Exception cause ) {
super( cause );
}
...
}

Using the Throwable class

I know that each java class should extend the Throwable class so that exceptions can be handled. Is this done by:
public class Test extends Throwable
or
public class Test throws Throwable?
Primitive types, or object whose class doesn’t extend Throwable cannot be thrown as exceptions.
Interpretation:
throw 3;
doesn't work because 3 is a primitive type.
throw new String();
doesn't work because String doesn't extend Throwable.
throw new RuntimeException();
works because RuntimeException is a subclass of Throwable.
I know that each java class should extend the Throwable class so that exceptions can be handled.
No, someone lied to you.
To handle exceptions, you need to keep in mind two things:
If it's a checked exception, then the class will refuse to compile if there is not a try...catch block wrapping the dodgy code, or if you don't declare the exception to be thrown.
try {
File f = new File("Foo.txt");
} catch (FileNotFoundException f) {
System.out.println("File doesn't exist!");
}
or:
public void doDodgyStuffWithFile throws FileNotFoundException { }
If it is an unchecked exception, then you will not get a compile-time failure for not catching the dodgy code, but you may get runtime exceptions from it.
String input = scanner.nextLine();
System.out.println(Integer.parseInt(input));
If you are throwing or catching the exception, be as specific as possible. Do not give into the temptation to throw/catch Exception, and never catch a Throwable.
When a class extends a Throwable, the class is a sub-class of Throwable and you can throw this class as a Throwable anywhere in you code.
class MyCoolThrowable extends Throwable{
try {
//... some error ...
} catch (MyCoolThroable t) {
//... handle the throwable
}
}
You add throws Throwable to a constructor or method so that the code that calls your constructor/method will be forced to use try-catch
void mySweetMethod() throws Throwable {
//...
}
try {
mySweetMethod();
} catch(Throwable t) {
//... handle it here
}
I think this clarified what you have read:)

Categories