Is the try-catch block necessary? - java

I started learning Java and I got confused about the necessity of try-catch blocks in some cases.
Let's say I have the following in my code:
System.out.println(args[0]);
If I don't have any arguments, I get the following error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at Main.main ...
But I wondered why do I need a try-catch block, with e.printStackTrace() in it, if the output will be the same as above and I also could identify the problem?

The purpose of try-catch blocks is NOT to have a simple e.printStackTrace() on them, but to manage possible exceptions on the code within.
By requiring a try-catch block, Java is forcing you to deal with the exceptions that can happen in your code and make a decision on what to do with them, in order to allow your code to fail gracefully.
Moreover, if you capture an exception with a catch, code can continue to execute after, which does not happen if the exception is not captured.

It is not necessary to catch all exceptions. In Java there is two types of exceptions: checked and unchecked. The rule is simple a checked exception has to be handled by the caller while an unchecked exception can be handled either by not catching it, or by catching it.
In your case since ArrayIndexOutOfBoundsException is an unchecked exception, you don't necessarily have to catch it . However if it is not handled your application will crash. Sometimes you want to save your app in case of an error, and in this case catching the exception is the way to do it. E.g: You ask an url from the user and try to connect to it. If the URL was invalid it will throw an exception. But instead of letting your application to crash you might want to notify the user and ask a new URL. So you will catch the exception and do the error handling.
Basically, to do a simply e.printStackTrace() is a bad practice. Do real error handling on the catch block or throw it away.

Related

under which conditions can the error escape try-catch with Exception class?

Which error conditions will not be caught by this try-catch block?
try
{
//some codes
}
catch (Exception e)
{
//log error
}
Background:
I implemented a server which runs external executables (with ProcessBuilder). So basically, I don't want the errors in the try block to kill the server. Catching Throwable might be the better option here, but I would like to know what else can escape Exception or more robust alternatives if any. Thanks!
Anything that's not an Exception.
Take a look at https://docs.oracle.com/javase/7/docs/api/java/lang/Exception.html for Javas own Exceptions (you can create your own by extending the Exception class).
Take note also that there is a difference between Error and Exception.
https://docs.oracle.com/javase/7/docs/api/java/lang/Error.html
Also, how do you plan on recovering from all Exceptions that exists?
If an Exception is thrown, you have reached a state where something is terribly wrong. Not knowing what that wrong is, it can be very hard to actually recover, leaving your server in a non-functional state. So while your server doesn't die in the sense that you see an Exception (and by that can trace back what went wrong), you will most likely be in a non-functional state anyhow.
If you haven't already done so, take a look at https://docs.oracle.com/javase/tutorial/essential/exceptions/ for dealing with exceptions. Or read it for an refresher.

What does mean by recoverable and un-recoverable exception or error

I'm trying to understand difference between error and exception but it looks same thing and on Oracle Official tutorials I read this line.
Checked exceptions are subject to the Catch or Specify Requirement.
All exceptions are checked exceptions, except for those indicated by
Error, RuntimeException, and their subclasses.
Now about I'm thinking it's same. But after searching more I found some difference as theoretical that.
Exception: are recoverable
Errors: not recoverable.
Exception Example:
try{
read file
}
catch(FileNotFoundException e){
// how I can recover here? can i create that file?
// I think we can just make log file to continue or exit.
}
Error Example:
try{
try to locate memory
}
catch(MemoryError e){
// I think we can just make log file to continue or exit.
}
Edited
I'm asking about recover-able and non-recoverable.
Error, as you already figured out, means you are in serious trouble. In a catch block you might be able to do something like logging, but basically that's it.
Non-recoverable exceptions are mostly runtime exceptions like NullPointerException. They are usually the result of some missed checks in the program code. Therefore the solution is normally to fix the code.
A recoverable exception is something that you know beforehand can happen and take certain measures. Think of a web application that calls some backend service. That service may or may not be available which can cause the execution of the operation to fail. Therefore you have a checked exception, in this case most likely a custom exception that you throw, and then handle it in the front end code in a manner where you tell the user, sorry backend service xy is down, try again later or contact support.
Recoverable does not mean that the application can do something to resolve the cause of the exception, though there may be cases where this is possible.
All classes that inherit from class Exception but not directly or indirectly from class RuntimeException are considered to be checked exceptions.Such exceptions are typically caused by conditions that are not under the control of the program.
Example
in file processing, the program can’t open a file if it does not
exist.
Recoverable
So It is very easy to know that if a file does not exists so you dont need to open that file hence that is recoverable
All exception types that are direct or indirect subclasses of RuntimeException (package java.lang) are unchecked exceptions. These are typically caused by defects in program’s code.
Example
ArrayIndexOutOfBoundsExceptions
ArithmeticExceptions
Error
Unrecoverable
So thatswhy program can not recover from these kind of errors or exceptions
Unrecoverable errors are the ones that put the application in an undefined state, like a broken database connection or a closed port, you may handle the error and continue to execute but it would not make sense. Modern languages like Rust and Go use the name panic for errors of these nature, to make the distinction clear. Best action to take is logging the error, if it is possible, and exiting the application.
A recoverable errors are the ones we can handle gracefully, like division by zero or validation errors. It is something expected and the resulting behavior is covered in the language spec. Yes, application behaves erratic when that a recoverable error happens but we can contain it or work around it.
The Object Throwable has 2 childs : Exception and Error.
All Exceptions are recoverable and all Errors are non-recoverable.
All Exceptions are recoverable because you can catch them and let your program continue its execution.
However all Errors , even when you add them to a catch block, will cause the abrupt termination of your program.
Examples of Errors: StackOverflowError, OutOfMemoryError,..
Remark : Checked and unchecked Exceptions are childs of Exception so recoverable.

catching exception and error

We have a piece of code for reading from queue
while(true){
try {
message = readMessageFromQueue();
processMesage(message); //Writes into DB and some other operation
}catch(Exception e) {
log the exception
}
}
Now there are ten threads which are spawned using executor service with the aim of running forever. However we have noticed after sometime we deploy(it can be 10-15 days or month) the number of thread is getting reduced(Write per second is also decreasing because of that).
The question is should we catch Error or only exception in the code which we want to run forever like this and is catching Exception can cause this problem ?
Yes, it's better to catch a Throwable there, not just Exception. Depending on your processing you might get, for example, a StackOverflowError that will kill your thread without logging. You might not be able to recover from it, but at least you can debug the problem latter.
From what I understand, you're asking if it is okay to catch by general Exception versus specific exceptions, like ArrayOutOfBoundsException. So, I guess my answer come down to whatever you prefer. You can catch by Exception, which isn't usually advised because you should always know what your code is doing and thus what could go wrong, but it does accomplish your tasks. Now, the reason you should catch by specific exceptions is that you can have different methods of handling different errors. Maybe the way you are handling the error isn't universally applicable to all errors, so when the thread sees an exception it isn't designed to expect, it crashes leaving you with one less thread.
I prefer catching specific exceptions of I can do something gracefully with that failure (like retry or do some default behavior). But if an exception means the program can't continue at all regardless, than catching the most generic exception and terminating is fine.
catching Exception is a "shotgun" approach to exception handling - "Whatever exception you will throw, I will catch it!".
catching a specific, ideally custom Exception is preferred mainly because you know where that exception is thrown, and you can gracefully handle that exception, or do some methods specifically for a certain exception. Therefore gives you more control of your application.
hope this helps.

Re-throwing RuntimeExceptions after catching Checked Exceptions [duplicate]

This question already has answers here:
What issues may ensue by throwing a checked exception as a RuntimeException?
(6 answers)
Closed 9 years ago.
In Java it is observed that there is a convention of re-throwing a RuntimeException just after handling a Checked Exception.
This way has both good and bad consequences. When the compiler forces something to be handled via a Checked Exception, the developer can just get rid of it by catching it and re-throwing it as a RuntimeException.
Can someone explain if this scenario can be considered as a good practice? If so, would this approach be less error prone or would it make the code base unstable?
Actually it is the incompetent attempts at handling checked exceptions which result in an unstable code base. Typically, you'll have this:
try {
//stuff
} catch (IOException e) {
log.error("Failed to do stuff", e);
throw e;
}
and then next level up you'll have to deal with it again, typically logging it all over and making a mess of the log files. It will be even worse if you don't rethrow:
try {
// do stuff
} catch (IOException e) {
return null;
}
Now the calling code has no idea something went wrong, let alone what. Compared to those attempts, this actually accomplishes exactly what the application logic needs:
try {
// do stuff
} catch (IOException e) {
throw new RuntimeException(e);
}
Now the exception can freely propagate up the call stack until it reaches the well-defined exception barrier, where it:
aborts the current unit of work;
gets logged at a single, unified spot.
In a nutshell, to decide whether to catch-and-handle or catch-and-rethrow, just ask yourself this question:
Must the occurrence of this exception abort the current unit of work?
if yes: rethrow an unchecked exception;
if no: provide meaningful recovery code in the catch-block. (No, logging is not recovery).
From many years of real-life experience I can tell you that more than 90% of all possible checked exceptions are of the "aborting" type and need no handling at the place of occurrence.
Argument against the language feature of checked exceptions
Today, checked exceptions are widely recognized as a failed experiment in language design, and here's the key argument in a nutshell:
It is not up to the API creator to decide on the semantics of its exceptions in the client code.
Java's reasoning is that exceptions can be divided into
exceptions resulting from programming errors (unchecked);
exceptions due to circumstances outside of programmer's control (checked).
While this division may be real to some extent, it can be defined only from the perspective of client code. More to the point, it is not a very relevant division in practice: what truly matters is at what point the exception must be handled. If it is to be handled late, at the exception barrier, nothing is gained by the exception being checked. If handled early, then only sometimes there is a mild gain from checked exceptions.
Practice has confirmed that any gains afforded by checked exceptions are dwarfed by real-life damage done to real-life projects, as witnessed by every Java professional. Eclipse and other IDEs are to blame as well, suggesting inexperienced developers to wrap code in try-catch and then wonder what to write in the catch-block.
Whenever you encounter a method which throws Exception, you have found yet another living proof of the deficiency of checked exceptions.
The idea of checked exceptions is "Java only" - as far as I know, no language after Java adopted this idea.
There are too many checked exceptions which are caught ... and silently ignored.
If you look at Scala, they dropped it as well - it's only there for Java compatibility.
In this tutorial on Oracle's web site, you will find this definition:
If a client can reasonably be expected to recover from an exception, make it a checked exception.
If a client cannot do anything to recover from the exception, make it an unchecked exception.
This notion has been adopted in Scala as well, and it works fine.
Technically speaking your proposal works. Discipline and code reviews are required in either way.
The term "can just get rid of it" is not totally correct in this case. This is getting rid of exceptions:
try {
} catch (Exception e){
e.printStacktrace();
}
This is the most common bad practice among the try-catch use. You are catching the exception and then, just printing it. In this case, the catch block catches the exception and just prints it, while the program continues after the catch block, as if nothing had happened.
When you decide to catch a block instead of throwing an exception, you must be able to manage the exception. Sometimes exceptions are not manageable and they must be thrown.
This is something you should remember:
If the client can take some alternate action to recover from the
exception, make it a checked exception. If the client cannot do
anything useful, then make the exception unchecked. By useful, I mean
taking steps to recover from the exception and not just logging the
exception.
If you are not going to do something useful, then don't catch the exception. Re-throwing it as a RuntimeException has a reason: as stated before, the program just cannot continue as nothing happened. This way, a good practice would be:
try {
} catch (Exception e){
//try to do something useful
throw new RuntimeException(e);
}
This means: you just caught an Exception (like an SQLException) from which you can't recover without stopping and resetting the thread. You catch it, you try to make something in between (like resetting something, closing open sockets, etc...) and then you throw a RuntimeException().
The RuntimeException will suspend the whole thread, avoiding the program continue as if nothing have happened. Furthermore, you were able to manage the other exception without just printing it.
It may or may not be okay, depending on the context, but it probably is not.
As a rule of thumb RuntimeExceptions should only be used to indicate programming errors (examples include IllegalArgumentException and IllegalStateException). They don't have to be checked exceptions because you generally assume your program is correct until proven otherwise and you cannot handle these exceptions in a meaningful manner (you have to release an updated version of the program).
Another valid use of runtime exceptions is when you use a framework that will catch and handle the exception for you. In such a scenario it would only be burdensome to having to declare the exception in every method when you are not going to handle it anyway.
So generally speaking I would say re-throwing a checked exception as a runtime exception is very bad practice unless you have a framework that will handle it properly.
The general rule is: you throw a checked exception when the caller might be able to do some kind of recovery when informed about it. Otherwise, throw an unchecked exception.
This rule applies when an exception is first thrown.
But this also applies when you catch an exception and are wondering whether to throw a checked or unchecked exception. So there is no convention to throw a RunTimeException after catching a checked one. It is decided in a case-by-case basis.
One small tip: if you are going to just re-throw an checked exception after catching one and do nothing else, most of the time it is alright to just not catch the exception and add it to the exceptions thrown by the method.

Notification when a certain exception has been raised in Java

I would like to know if there is a way where we can get notified when a certain exception has been thrown even if it was already caught.
I have an exception which is caught by the underlying framework which threw the exception. I have been trying to use this exception from outside of their try-catch (surrounding it essentially) as a trigger point to run some code and trying to find a way to do it.
Any way to do it?
Thanks!
You gave no context, so here some possibilities:
set a breakpoint in the appropriate constructor and run in debug mode
use aspects, e.g. aspectj or spring
put your extensions in the exception's constructor
put a try-catch around the code that causes the exception
P.S.: for the case you didn't know, you can catch RuntimeExceptions the same way you catch checked exceptions.
If an exception is already caught by the framework, there is no way of you catching it with a try-catch block.
You're trying to do this:
try {
try {
throw new Exception();
} catch(Exception e) {
e.printStackTrace();
}
} catch(Exception e) {
System.out.println("Caught from the outside!");
}
which will fail, the exception's StackTrace will be printed, but the "Caught from the outside!" will not be printed. This is due to the fact that the exception thrown in the middle has already been caught, exceptions cannot be caught twice, or that would defeat the purpose of error handling; once an error is handled, no need to notify higher levels about it ;)
From what I understand, you have no access to the source, the exception is caught and handled outside of your scope of access, and you want to make it do something?
The only solution that's immediately apparent to me is PowerMock, a library allows you to override constructors and return objects of your own creation. It's typically only used in testing, and I discourage using it for any other purpose, but you could use it to replace all instances of that exception with an extension of the original exception, with your own code added in.

Categories

Resources