Why is catch block optional? - java

I have the following code
public static void nocatch()
{
try
{
throw new Exception();
}
finally
{
}
}
Which gives the error
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Unhandled exception type CustomException
My Question is why was it designed that the catch block is optional, when there is no way of getting around not having a catch?
From finally()'s perspective, I understand that
finally should have atleast a try block, catch is optional. The point of finally blocks is to make sure stuff gets cleaned up whether an exception is thrown or not. As per the JLS
A finally clause ensures that the finally block is executed after the try block and any catch block that might be executed, no matter how control leaves the try block or catch block.
Edit:
By adding a return in the finally block, compiler does not give the error WHY?!
public static void nocatch()
{
try
{
throw new Exception();
}
finally
{
return; //By adding this statement, the compiler error goes away! Please let me know why
}
}

My Question is why was it designed that the catch block is optional, when there is no way of getting around not having a catch?
Yes there is: Declare that the method throws the exception:
public static void nocatch() throws CustomException
{
try
{
throw new CustomException();
}
finally
{
}
}
try/finally without catch is to ensure that you clean up anything you need to clean up, even if you aren't handling the exception yourself. (Be sure not to allow any other exception to be thrown from within finally, or you'll hide the primary exception.)
Here's an example to play with (live copy):
private static class CustomException extends Exception {
}
public static void main (String[] args) throws java.lang.Exception
{
try
{
System.out.println("Calling nocatch(false)");
nocatch(false);
}
catch (CustomException ce) {
System.out.println("Caught CustomException for false case");
}
try
{
System.out.println("Calling nocatch(true)");
nocatch(true);
}
catch (CustomException ce) {
System.out.println("Caught CustomException for true case");
}
}
public static void nocatch(boolean foo) throws CustomException
{
try
{
if (foo) {
System.out.println("Throwing");
throw new CustomException();
}
}
finally
{
System.out.println("In finally");
}
System.out.println("Reached outside the try/finally block");
}
Output:
Calling nocatch(false)
In finally
Reached outside the try/finally block
Calling nocatch(true)
Throwing
In finally
Caught CustomException for true case
As you can see, the finally block's code runs regardless of whether an exception occurred, but the code after the try/finally doesn't.
Re your follow-up asking why adding return within the finally makes the error go away:
try
{
throw new CustomException();
}
finally
{
return; // <=== Makes the compiler happy (but don't do it!)
}
Interesting edge case! It's because the code in the finally block always runs, and so you'll always return rather than throw, hiding the exception that occurred. E.g., this is the sequence:
throw new CustomException() throws the exception, which transfers control to the finally block
Code in the finally block issues a normal return from the method
This hides the fact the exception occurred; in effect, you've "handled" the exception (without actually handling it) via the finally block. In general, this isn't a good idea; use catch to handle exceptions, or declare them on the method so calling code can handle them.

Related

Exception doesn't need to be thrown to be caught, but IOException does

Why does the following code compile fine, but the method being called does not need to throw Exception? Isn't Exception a checked exception and not an unchecked exception? Please clarify.
class App {
public static void main(String[] args) {
try {
amethod();
System.out.println("try ");
} catch (Exception e) {
System.out.print("catch ");
} finally {
System.out.print("finally ");
}
System.out.print("out ");
}
public static void amethod() { }
}
If I want to use a try catch with IOexception (a checked exception), the method being called needs to throw IOException. I get this.
import java.io.IOException;
class App {
public static void main(String[] args) {
try {
amethod();
System.out.println("try ");
} catch (IOException e) {
System.out.print("catch ");
} finally {
System.out.print("finally ");
}
System.out.print("out ");
}
public static void amethod() throws IOException { }
}
Isn't 'Exception' a checked exception and not an unchecked exception?
Yes, it is.
But even if we know the method doesn't throw Exception itself, the code catch(Exception e){ could still execute. The code in the try block could still throw something that inherits from Exception. That includes RuntimeException and its subclasses, which are unchecked.
catch(IOException e){, on the other hand, can only catch checked exceptions. (Java doesn't allow multiple inheritance, so anything that's a subclass of IOException can't possibly be a subclass of RuntimeException.) The compiler can fairly easily figure out that none of the code in the try block can possibly throw an IOException (since any method throwing a checked exception must explicitly say so) which allows it to flag the code.
Normally there would be a compiler error for having a try block that never throws a checked exception that you have a catch block for, but the behavior you're observing comes from the fact that the Java Language Specification treats Exception specially in this circumstance. According to §11.2.3:
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 is reasonable because Exception (and its superclass Throwable) can be used to catch exceptions that extend RuntimeException also. Since runtime exceptions are always possible, the compiler always allows Exception to appear in a catch clause regardless of the presence of checked exceptions.

Does Java's try-with-resources catch errors or just exceptions?

I have some junit tests which create some resources which should also be closed.
One way to implement this logic is using the #Before and #After approach.
What I did was to encapsulate the creation in some utility class to be reused. For example:
class UserCreatorTestUtil implements AutoClosable {
User create() {...}
void close() {...}
}
The whole point is for the object to close itself, rather than needing to remember to close it in #After.
The usage should be:
#Test
void test() {
try (UserCreatorTestUtil userCreatorTestUtil = new UserCreatorTestUtil()) {
User user = userCreatorTestUtil.create();
// Do some stuff regarding the user's phone
Assert.assertEquals("123456789", user.getPhone());
}
}
The problem is that junit's assert keyword throws an Error - not Exception.
Will the try-with-resource "catch" the Error and invoke the close method?
* Couldn't find the answer in the try-with-resources documentation.
It does not catch anything. But it does finally close all resources.
finally blocks are run even when an Error is thrown.
The pseudo-code of a basic try-with-resources statement is (cf Java Language Specification §14.20.3.1):
final VariableModifiers_minus_final R Identifier = Expression;
Throwable #primaryExc = null;
try ResourceSpecification_tail
Block
catch (Throwable #t) {
#primaryExc = #t;
throw #t;
} finally {
if (Identifier != null) {
if (#primaryExc != null) {
try {
Identifier.close();
} catch (Throwable #suppressedExc) {
#primaryExc.addSuppressed(#suppressedExc);
}
} else {
Identifier.close();
}
}
}
As you can see it catches Throwable not Exception which includes Error but only to get the primary exception in order to add as suppressed exceptions any exceptions that occurred while closing the resources.
You can also notice that your resources are closed in the finally block which means that they will be closed whatever happens (except in case of a System.exit of course as it terminates the currently running Java Virtual Machine) even in case an Error or any sub class of Throwable is thrown.
Try-with-resources don't catch anything in and of themselves.
However, you can attach a catch block to the end of the try-with-resources block, to catch whatever types of Throwable you like:
try (UserCreatorTestUtil userCreatorTestUtil = new UserCreatorTestUtil()) {
// ... Whatever
} catch (RuntimeException e) {
// Handle e.
} catch (Exception | Throwable t) {
// Handle t.
}
The idea behind try-with-resources is to make sure that the resources should be closed.
The problem with conventional try-catch-finally statements is that let's suppose your try block throws an exception; now usually you'll handle that exception in finally block.
Now suppose an exception occurs in finally block as well. In such a case, the exception thrown by try catch is lost and the exception generated in finally block gets propagated.
try {
// use something that's using resource
// e.g., streams
} catch(IOException e) {
// handle
} finally {
stream.close();
//if any exception occurs in the above line, than that exception
//will be propagated and the original exception that occurred
//in try block is lost.
}
In try-with-resources the close() method of the resource will get automatically called, and if the close() throws any exception, the rest of the finally isn't reached, and the original exception is lost.
Contrast that with this:
try (InputStream inputStream= new FileInputStream("C://test.txt")){
// ... use stream
} catch(IOException e) {
// handle exception
}
in the above code snippet, the close() method automatically gets called and if that close() method also generated any exception, than that exception will automatically get suppressed.
See also: Java Language Specification 14.20.3
Misconception on your end: try-with-resources does not do a catch.
It does a final finally, therefore the kind of "problem" doesn't matter.
See the JLS for further information!

What's the difference between code inside finally block and code after finally block?

I was wondering what's the difference between code inside finally block and code after finally block
A small test program shows the difference:
public class FinallyTest {
public static void main(String[] args) throws Exception {
try {
boolean flag = true;
if (flag) {
throw new Exception("hello");
}
} finally {
System.out.println("this will get printed");
}
System.out.println("this won't show up");
}
}
The program throws an exception, the JVM executing the program catches it and prints it out.
What gets written to the console is:
this will get printed
Exception in thread "main" java.lang.Exception: hello
at snippet.FinallyTest.main(FinallyTest.java:7)
Once the exception is thrown the only things that that thread will execute (until the exception is caught by the JVM) are finally blocks (where the exception is leaving a try-block that the finally belongs to).
Here I am adding more to the example provided above and may help someone in the future and hope will avoid some confusion.
Lets Start.
Actually, it depends on the flow control of the program. That means if the program is written in such a way that if your code is handling the exceptions thrown in the try blocks and if you are handling them in the catch block, then your code after finally block will get executed after the code inside the finally block.
Example 1: here the exceptions have been handled and hence the code after finally, block executes.
public class TestFinally {
public static void main(String[] args) throws Exception {
try {
boolean flag = true;
if (flag) {
throw new Exception("hello");
}
}
catch(Exception e){
System.out.println("catch will get printed");
}
finally {
System.out.println("this will get printed");
}
System.out.println("this won't show up");
}
}
result:
catch will get printed
this will get printed
this won't show up
Example 2: if the exceptions in the try block have not been handled properly as told by Nathan above, then the code after the finally block does not get executed.
public class TestFinally {
public static void main(String[] args) throws Exception {
try {
boolean flag = true;
if (flag) {
throw new Exception("hello");
}
}
// not handling the exception thrown above
/*catch(Exception e){
System.out.println("catch will get printed");
}*/
finally {
System.out.println("this will get printed");
}
System.out.println("this won't show up");
}
}
result:
this will get printed
Exception in thread "main" java.lang.Exception: hello
at com.test.TestFinally.main(TestFinally.java:36)
So conclusively, to sum up, the code inside the finally block gets executed always except in some cases where the thread has been stopped or killed before the finally block or in case if there are any exit programs written in a try block. Whereas the code after finally depends on the code written in try-catch-finally blocks and the exception handling.
If the catch block re-throws an exception (or throws a new one), the finally block is executed. Anything after the finally block will not be executed.
The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated. - http://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html
If you throw the exception on the catch block, or if you return something on your try block, it will execute the finally block. If not on the finally block (after try/catch/finally) it wont work. Here is a simple example for you to understand: Try it without the finally block and you will see that the line where it prints the message "Closing resources..." will never be executed.
try {
return "Something";
} catch (Exception e) {
throw e;
} finally {
System.out.println("Closing resources (Connections, etc.)...");//This will always execute
}

Instantiating a java if statement referencing an error

How would one write an "if statement" that checks if an error occurred in a method if so it would start a separate method that deals with the error otherwise open the next method
It is called Exception Handling.
Example:
void someMethod()
{
try
{
// Open a File
}
catch(FileNotFoundException e)
{
// Call another method
}
finally
{
// this block executes whether exception occurs or not
}
// Continue execution
}
Use a try catch statement for this. Assumign you want to crash out if the first method errors (after dealing with the exception) then the below format should work
try {
methoda();
} catch(Exception e) {
methodToDealWithError(e);
throw(e);
}
methodb();
i think try-catch block will do it for you. call your first method in try block, then call your method which deals with exceptions in catch block.
Why not just use Exceptions? Make the method throw an exception on error, catch the exception in the calling code, place error handling in the catch block??? That's what Exceptions are for!
It depends on how the method reports the error. If it returns "false" upon error you can do a trivial test:
boolean res = method();
if (!rest) {
// manage error
}
If the method however raises exception, you have to catch them with:
try {
method();
} catch (Exception e) {
// Manage exception or raise
}
Actually it depends on how method is implemented. Can you give some more info ?
methodA: The first method, it throws an exception in case en error occurs
methodB: next Method to execute, if no error occurs
methodC: error dealing method
try{
methodA();
methodB();
catch(Exception e){
methodC();
}
use Exception handling by using try catch block as
try {
Place Your Code Here...
} catch(Exception e) {
callAnotherMethodHere();
}

Try-Catch-Throw in the same Java class

Is it possible to catch a method in the current class the try-catch block is running on? for example:
public static void arrayOutOfBoundsException(){
System.out.println("Array out of bounds");
}
.....
public static void doingSomething(){
try
{
if(something[i] >= something_else);
}
catch (arrayOutOfBoundsException e)
{
System.out.println("Method Halted!, continuing doing the next thing");
}
}
If this is possible how will it be the correct way to call the catch method?
If this is not possible, could anyone point me in the right direction, of how to stop an exception from halting my program execution in Java without having to create any new classes in the package, or fixing the code that produces ArrayOutOfBoundsException error.
Thanks in Advance,
A Java Rookie
What you are wanting to do is handle an Exception.
public static void doingSomething(){
try {
if (something[i] >= something_else) { ... }
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Method Halted!, continuing doing the next thing");
}
}
That's all you need. No extra classes, no extra methods.
An Exception is a special type of class that can be "thrown" (you can throw it yourself by using the throw keyword, or Java may throw one for you if, for example, you try to access an array index that does not exist or try to perform some operation on a null). A thrown exception will "unwrap" your call stack ("escaping" from each function call) until your program finally terminates. Unless you catch it, which is exactly what the syntax above does.
So if you were writing a function a() that called a function b() that called a function c() and c() threw an exception, but the exception was not caught in b() or c(), you could still catch it in a():
void a() {
try {
b();
catch (SomeExceptionClass e) {
// Handle
}
}
That said, if it is possible to prevent an exception from being thrown in the first place, that is often a better idea. In your particular case, this would be possible since all arrays in Java know their own length:
public static void doingSomething(){
if (i >= something.length) {
System.out.println("Method Halted!, continuing doing the next thing");
} else {
if (something[i] >= something_else) { ... }
}
}
Hmm.. I think you are a little bit confused. You don't catch a method with try catch blocks. You catch Exceptions. Exceptions are more like things.
This alone (note the capital "A" of ArrayOutOfBoundsException) will prevent your program to terminate even if that Exception is thrown. You don't need to declare a "arrayOutOfBoundsException()" method.
public static void doingSomething(){
try
{
if(something[i] >= something_else);
}
catch (ArrayOutOfBoundsException e)
{
System.out.println("Method Halted!, continuing doing the next thing");
}
}
Note the little "e"? That's the reference you can use to refer to this Exception. So, you can ask things to this Exceptions using this little local variable. For example, if you want to print where the exception happened, you can do e.printStackTrace(); .
You catch Exceptions, with a try-catch block. Not sure if you can catch methods with this.
public static void myMethod(){
try {
// check for some given condition
}
catch (conditionNotSatisfied e) {
System.out.println("Condition was not satisfied, you tried to do something which is not allowed");
}
}
The 'e' in the catch() is the reference used for referring to an Exception.
Exception refers to this when it wishes to check your given condition and return you a warning or error about the condition not getting satisfied.
I think you mean to have the arrayOutOfBoundsException method throw the exception caused... If i understand correctly:
public static void arrayOutOfBoundsExceptionMethod() throws ArrayIndexOutOfBoundsException {
\\...
\\ code that throws the exception
}
.....
public static void doingSomething(){
try
{
if(something[i] >= something_else);
arrayOutOfBoundsExceptionMethod();
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println("Method Halted!, continuing doing the next thing");
}
}
Is that what you are asking?
I'm trying to understand what you're asking, your terminology is wrong in places :) If you try and set an index out of bounds, you'll get a built-in exception anyway, ArrayIndexOutOfBoundsException. You can catch this and use this inside the method, or throw it using a class XX throws ArrayIndexOutOfBoundsException declaration in the header of the method, so that the invoking method can catch it (its not required to catch an ArrayIndexOutOfBoundsException as it's a RuntimeException -- i.e., nothing happens if it goes uncaught, it's unchecked.
See this wiki article for more details: http://en.wikibooks.org/wiki/Java_Programming/Throwing_and_Catching_Exceptions.
It is not clear what you mean by "Is it possible to catch a method". In your case, you should write your code as :
if(i < something.length && something[i] >= something_else);
No ArrayOutOfBoundsException is needed.

Categories