I have a method which under certain conditions may throw an exception, but most of the time will not. I would like to require anyone who calls this method to catch the exception if they call it under the "dangerous" conditions, but not have to worry about it under "safe" conditions.
public static boolean dangerousSituation; // set somewhere else
public sometimesDangerousMethod() throws MyException {
// some code
// may throw MyException if dangerousSituation == true
// will never throw MyException if dangerousSituation == false
}
otherMethod() {
dangerousSituation = false;
sometimesDangerousMethod(); // shouldn't have to worry about MyException
// if it can't possibly happen
dangerousSituation = true;
try {
sometimesDangerousMethod(); // should be required to handle
// MyException if it may possibly happen
} catch(MyException e) {
// handle MyException
}
}
That is, I would like to require a try/catch block around sometimesDangerousMethod() if and only if dangerousSituation == true.
The reason I want this is because I don't want to bother developers with exception handling if they stick to safe situations anyway. But of course, if a developer does use a dangerous situation, the compiler should let him know.
Is there some way to get this behavior in Java?
I have considered breaking up sometimesDangerousMethod() into two methods: one dangerous, one safe. But I don't think this makes sense since this would require developers to be aware of two methods which do basically the same thing.
The functionality you're looking for doesn't exist. You can either split it into two methods, or your coworkers will have to use a try-catch. Sorry, but sometimes the answer is just "No".
#mypetlion is accurate on the most part.
There are a couple of other options for you to consider is:
Would it be possible to handle the exception inside of sometimesDangerousMethod() instead of otherMethod()? If so, then you could pass in the logging/metric object to the method, try/catch inside of the method, and log an error message or update a metric when this occurs. This way, you don't have to worry about try/catch in the case that the exception doesn't occur.
You could break it up into 2 methods like #mypetlion mentioned and with a bit of organization, it may be good enough code:
`
public class Solution {
public static boolean dangerousSituation; // set somewhere else
public void notDangerousMethod(){
// will never throw MyException
}
public void dangerousMethod() throws MyException {
// throws MyException
}
public void sometimesDangerousMethod() throws MyException {
if(dangerousSituation){
dangerousMethod();
} else {
notDangerousMethod();
}
}
public void otherMethod() {
dangerousSituation = false;
// Option 1:
if(dangerousSituation){
try{
dangerousMethod();
} catch(MyException e) {
// handle MyException
}
} else {
notDangerousMethod();
}
// Option 2:
try {
sometimesDangerousMethod(); // should be required to handle
// MyException if it may possibly happen
} catch(MyException e) {
// handle MyException
}
}
`
Depending on contents of sometimesDangerousMethod(), this may be overkill. If it is a few very simple lines of logic, it might be worth it to implement your original design. I don't think the developers would mind :)
You're missing the point of the word Exception. Your code should not throw an Exception unless there is an exceptional situation. Properly designed code that consumes your code still needs to handle the possibility of an exceptional situation.
You shouldn't worry so much about the users of your method having to worry about exceptions.
If your method can fail for whatever reason, it should declare the exception (or use an unchecked exception) and throw the exception if it really fails. That's exactly what exceptions are for.
So I think dangerousSituation is in fact a very dangerous flag. In the code you propose, setting the flag translates to "do not tell me if the method fails [because I know better than the method's implementation that there will not be a failure]".
So, the only reason for not throwing can be a method that will surely succeed. And any decent Java developer should know how to handle exceptions (typically by letting them pass through to a top level where all exceptions are caught and logged).
Related
I am confused about best practice in situation when you need throw multiple exceptions.
Let say that we have exceptions declared as it is shown below.
public class DaoException extends Exception
public class ClientNotFoundException extends DaoException
public class NotUniqueResultException extends DaoException
Now we have а method, which can throw ClientNotFoundException and also NotUniqueResultException. What is better to be appled to the throws clause?
getClientByNumber(Long number)
throws ClientNotFoundException, NotUniqueResultException
or
getClientByNumber(Long number) throws DaoException
?
How do you solve this situation in your code? Do you creatе your own exception hierarchy in your applications?
Is there other possible way how to solve it?
My personal opinion is that you should be as descriptive as possible for all the possible cases that may occur when the method does some activity, i.e. I would advice to do:
getClientByNumber(Long number)
throws ClientNotFoundException, NotUniqueResultException
The reason for this is that the one that invokes the method will have to deal with both of the cases in which your method throws an exception. Your method may throw different exception under different circumstances, and the way an exception is caught may differ, depending on the type of the exception. For example:
public void myMethod() {
try {
getClientByNumber(1);
} catch (NotUniqueResultException e) {
//something that deals with the exception of that specific type.
} catch (ClientNotFoundException e) {
//something else that deals with the exception of that specific type.
}
}
In my experience it is often best to be specific; thus choosing the throws ClientNotFoundException, NotUniqueResultException solution. That way it is more clear to the user which exceptions can be thrown and what they mean which makes it much easier to handle them.
Creating a hierarchy of Exceptions for your application can be a good idea if the exceptions in question are actually related. However in many cases this is not required; for example the NotUniqueResultException could extend IllegalStateException (as it is, from what I can see, an illegal state).
It's a good idea to declare every type of exception you expect to throw, even those that are runtime exceptions.
One of the reasons for this is Javadoc. Imagine you have something like this.
public void foo( String bar ) throws NullPointerException, IllegalArgumentException {
if (bar == null) {
throw new NullPointerException( "bar must not be null" );
}
if (bar.equals( "123" ) {
throw new IllegalArgumentException ( "bar must not have valu 123" );
}
...
}
And in your Javadoc you can document exactly what is thrown when. This is incredibly useful for users of your code, even if they don't want to handle them differently. (Of course you can add the #throws tags to the Javadoc manually, but it's better to be prompted.)
Before Java 7, dealing with many exceptions in one catch was quite complicated, which tempted developers to simplify their throws clauses but there's no justification for that any more.
Try-multi-catch:
try {
getClientByNumber(Long number);
} catch ( ClientNotFoundException | NotUniqueResultException ex ) {
...
}
This eliminates the need to repeat your catch block (or even worse, catch Exception).
Re-throwing made easy
If for some reason you do want to catch every exception, log it and re-throw it, you can do this:
public void foo() throws ClientNotFoundException, NotUniqueResultException {
try {
getClientByNumber(Long number);
} catch ( Exception ex ) {
...
throw ex; //the compiler knows that at this point `ex` is either an unchecked exception, or one of the two declared checked exceptions, therefore this re-throw is valid
}
}
We need to have two functions. They do the same thing but one handles the exceptions and one throws the exception. Note: If to handle exception, the exception has to be handled in the commonFunc() below. It would not work to handle the exception in functionHandlesEx() because to handle the function it needs the variable only available in commonFunc(). In order to re-use code, we got the following. Do you see any problem with it (I can see one problem is: the function throws exception but actually no exception is thrown when isExceptionHandled is true----but Java allows this)? Any better way to do this? We are in Java 6. Thanks.
public void functionThrowsEx() throws Exception e
{
commonFunc(false); //false means does not handle exception
}
public void functionHandlesEx()
{
try
{
commonFunc(true); //true means handle exception
}
catch (Exception e)
{
// do nothing as exception handled
}
}
private void commonFunc(final boolean isExceptionHandled) throws Exception
{
try
{
....
}
catch (Exception e)
{
if (isExceptionHandled)
{
//handle the exception
}
else
{
throw e;
}
}
}
This seems like an overly complicated approach to handling the exception. I understand its toy code to show what you are doing, but I haven't encountered many reasons to create nested calls in order to handle exceptions.
Ideally, the code that can cause the exception should have the means to handle the exception in it, using try...catch, and maybe finally. This logical flow looks like it would be pretty complex in a non-trivial application, and would lead to increased complexity and difficulty in debugging.
You should get rid of the two functions, and avoid nesting try/catch blocks. If you must nest them, make it has straigtfoward as possible by keeping the logic in the same method.
From the code, I'm guessing you want to handle the exception differently based on the state of the program. This code is too complex, and will be difficult to understand for a non trivial app. A better way would be to keep functionHandlesEx and put the exception recovery logic in the handler function.
public void functionHandlesEx() {
try {
//logic here;
}
}
catch (Exception e) {
if(iWantToHandleException) {
//handle exception
}
//do nothing otherwise. Use the finally block for anything else they have in common.
}
}
This is much simpler to understand, and it shouldn't be too hard to refactor it into this form.
I have a method which is getting an exception as a parameter to a particular method. This method needs to do perform different logic based on the type of exception. Between below two ways of handling this.. what is the most efficient way (is there a third better way).. and why
public void processException(Exception ex) {
try {
throw ex;
} catch(CustomException e1) {
//do something
} catch (CustomException2 e2) {
//do something else
}
}
or
public void processException(Exception ex) {
if (ex instanceof CustomException) {
// do something
} else if (ex instanceof CustomException2) {
// do something else
}
}
Efficiency aside, the second way is preferred, because the exception is not thrown in a non-exceptional situation. The first way to "dispatch" uses exception throwing in a regular control flow, which makes it harder to read your program.
Besides, the two methods are not identical: the first program must be declared as throwing a checked exception, because not all subtypes are handled by the catch blocks.
If you are dealing with custom exceptions that your program defines, you have a way to avoid checking the subtype: since Exception objects are regular classes, you could add a package-visible method to them, and have them implement a package-visible interface holding that method. Exceptions would then be able to override that method, letting you use a regular "virtual" dispatch rather than checking for the exact class type at runtime.
Here is an illustration of this approach: let's say you want your exceptions to write themselves to a log file. You can do this as follows:
interface LoggableException {
void logToFile();
}
public class CustomExceptionOne extends Exception implements LoggableException {
...
public void logToFile() {
// Do something
}
}
public class CustomExceptionTwo extends Exception implements LoggableException {
...
public void logToFile() {
// Do something else
}
}
public void processException(Exception ex) {
if (ex instanceof LoggableException) {
LoggableException lEx = (LoggableException)ex;
lEx.logToFile();
}
}
The first one is a very bad idea. Logic should not be expressed as exception catching. They're expensive, whether you realize it or not.
I don't like the second one, either. When you see if/else logic, you should think about polymorphism.
Obviously the second option is better. All the Exceptions are eventually objects and it is better, safe and recommended to perform instance of check to determine the type of object.
Throwing and catching Exceptions are expensive operations and should only occur in exceptional circumstances. In addition, your method to handle the exception is probably being called because the exception was already thrown. I wouldn't throw it again.
Either instanceof, or overloaded processException like rgettman suggests. Another alternative is
public void processException(Exception e) {
Class eClass = e.getClass();
if (eClass == CustomeException.class) { // This exception is most likely.
// do something
} else if (eClass == CustomException2.class) {
// do something
} else if (eClass == CustomException3.class) {
// do something
} else if (eClass == CustomException4.class) {
// do something
}
}
I would suggest short circuiting the if/else if statements with the most likely exception class.
public void foo() {
begin();
try {
...
commit();
} catch (Exception e) {
rollback();
throw e;
}
}
In the sample above, there is an error because foo has no throws Exception. Adding that wouldn't make do the method's usability a lot of good either.
What's the best way to do this? How do you do something if an error occurs without really "handling" the error?
Since Java 8 we use
/**
* Cast a CheckedException as an unchecked one.
*
* #param throwable to cast
* #param <T> the type of the Throwable
* #return this method will never return a Throwable instance, it will just throw it.
* #throws T the throwable as an unchecked throwable
*/
#SuppressWarnings("unchecked")
public static <T extends Throwable> RuntimeException rethrow(Throwable throwable) throws T {
throw (T) throwable; // rely on vacuous cast
}
You can rethrow a checked exception, but only by avoiding the compilers checked exception validation.
public void foo() throws MyCheckedException {
begin();
try {
...
commit();
} catch (Exception e) {
rollback();
// same as throwing an exception without the compiler knowing.
Thread.currentThread().stop(e);
}
}
Before you use stop() you should read http://download.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
Thread.currentThread().stop(e) .. is behaviorally identical to Java's throw operation, but circumvents the compiler's attempts to guarantee that the calling method has declared all of the checked exceptions that it may throw:
At least two approaches come to mind, which are usually going to be combined depending on what you want foo to do:
1. Catch and rethrow only the relevant exceptions
There are only so many exceptions the code in your main flow can throw (probably mostly SqlExceptions). So only catch and rethrow those, and declare that you're doing so. More to the point, rethrow only the ones you're not actually handling (in your simplified sample code, you're not handling any, but your real life code is probably more subtle).
Mind you, some of the exceptions may be runtime exceptions, and so you may want to combine this with the below.
2. Don't catch the exception at all
Like this:
// Signature changes to include any exceptions that really can be thrown
public void foo() throws XYZException, ABCException {
// A flag indicating that the commit succeeded
boolean done = false;
begin();
try {
// Don't have any `return` statements in here (or if you do,
// set `done` to `true` first)
...
commit();
done = true; // Commit didn't throw an exception, we're done
} finally {
// finally clause always happens regardless
if (!done) {
// We must be processing an exception; rollback
try {
rollback();
} catch (Exception e) {
// quash it (e.g., leave this block empty), we don't want
// to mask the real exception by throwing a different one
}
}
}
}
Naturally your signature needs to include any exceptions that may be thrown in the main flow, but that's what you're trying to do, if I'm understanding you correctly.
Again, you may well combine these two approaches, because you may want to handle some exceptions and not others.
Wrap it with some RuntimeException which is unchecked.
Adding that wouldn't make do the method's usability a lot of good either.
No. It will be good at documentation, also caller will take care handling it.
Also See
exception-thrown-inside-catch-block-will-it-be-caught-again
throws-or-try-catch
I'd say that in this case rolling back is handling the exception appropriately. It's one of the few cases where it's legitimate to catch and re-throw.
Simply catching and logging an exception is not what I would consider handling. Rather than rethrowing, in that case I'd rather see checked exceptions added to the method signature and let it bubble up.
you may throw a subclass of RuntimeException - they don't require a catch()
the key point is, why should you throw a new Exception from a catch block.
if you use catch then handle your exception there in your catch. If you have to inform the caller method with an exception, then don't catch the exception with try-catch, instead, sign your method with throws and let the caller catch the e xception.
or throw a RuntimeException, i find this idea less useful because of lack of readability, then you don't need to sign your method with throws.
Here you've chanced on one of the biggest religious schisms in the Java, ( if not wider ) , world. It boils down to those that feel, as TJ seems to, and I do too, that checked exceptions are valuable for many reasons, VS the Rod Johnson/Spring school that in the design of Java, checked exceptions were used in many instances where they shouldn't, say closing a resultset or socket, so because it was wrongly used in many cases, it makes them useless so all exceptions should be unchecked. There are many classes in the Spring framework that are very thin wrappers around standard Java objects, but convert checked exceptions to unchecked. It drives me berserk!
Anyway, put me down as strongly agreeing with everything TJ has said, but know that you'll probably never find a "right" answer.
It's worth mentioning some advances in this area.
First, in Java 7, it's possible to catch and throw generic exceptions, as long as what's declared inside the try block is caught or declared in the outer block. So this would compile:
void test() throws SQLException {
try {
conn.commit();
} catch (Throwable t) {
// do something
throw t;
}
}
This is well explained here : http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
Another way is described here : http://blog.jooq.org/2012/09/14/throw-checked-exceptions-like-runtime-exceptions-in-java/
The reason you may want to use that has often to do with lambdas, or throwing exceptions from some generic methods. I ran into this when I wanted to replace repeating constructs of:
try {
do_operation
flag_success
} catch (Throwable e) {
flag_error
throw e;
}
With using a method of:
public static void wrapExec(RunnableT s) {
try {
s.run();
flag_success
} catch (Throwable t) {
flag_error
doThrow(t);
}
}
and therefore replacing the whole try/catch block with just
wrapExec(()->{do_operation})
(Late edit: This question will hopefully be obsolete when Java 7 comes, because of the "final rethrow" feature which seems like it will be added.)
Quite often, I find myself in situations looking like this:
do some initialization
try {
do some work
} catch any exception {
undo initialization
rethrow exception
}
In C# you can do it like this:
InitializeStuff();
try
{
DoSomeWork();
}
catch
{
UndoInitialize();
throw;
}
For Java, there's no good substitution, and since the proposal for improved exception handling was cut from Java 7, it looks like it'll take at best several years until we get something like it. Thus, I decided to roll my own:
(Edit: Half a year later, final rethrow is back, or so it seems.)
public final class Rethrow {
private Rethrow() { throw new AssertionError("uninstantiable"); }
/** Rethrows t if it is an unchecked exception. */
public static void unchecked(Throwable t) {
if (t instanceof Error)
throw (Error) t;
if (t instanceof RuntimeException)
throw (RuntimeException) t;
}
/** Rethrows t if it is an unchecked exception or an instance of E. */
public static <E extends Exception> void instanceOrUnchecked(
Class<E> exceptionClass, Throwable t) throws E, Error,
RuntimeException {
Rethrow.unchecked(t);
if (exceptionClass.isInstance(t))
throw exceptionClass.cast(t);
}
}
Typical usage:
public void doStuff() throws SomeException {
initializeStuff();
try {
doSomeWork();
} catch (Throwable t) {
undoInitialize();
Rethrow.instanceOrUnchecked(SomeException.class, t);
// We shouldn't get past the above line as only unchecked or
// SomeException exceptions are thrown in the try block, but
// we don't want to risk swallowing an error, so:
throw new SomeException("Unexpected exception", t);
}
private void doSomeWork() throws SomeException { ... }
}
It's a bit wordy, catching Throwable is usually frowned upon, I'm not really happy at using reflection just to rethrow an exception, and I always feel a bit uneasy writing "this will not happen" comments, but in practice it works well (or seems to, at least). What I wonder is:
Do I have any flaws in my rethrow helper methods? Some corner cases I've missed? (I know that the Throwable may have been caused by something so severe that my undoInitialize will fail, but that's OK.)
Has someone already invented this? I looked at Commons Lang's ExceptionUtils but that does other things.
Edit:
finally is not the droid I'm looking for. I'm only interested to do stuff when an exception is thrown.
Yes, I know catching Throwable is a big no-no, but I think it's the lesser evil here compared to having three catch clauses (for Error, RuntimeException and SomeException, respectively) with identical code.
Note that I'm not trying to suppress any errors - the idea is that any exceptions thrown in the try block will continue to bubble up through the call stack as soon as I've rewinded a few things.
There are a couple of way to handle this. The first is my preference if you don't need to know what the exception was.
boolean okay = false;
try {
// do some work which might throw an exception
okay = true;
} finally {
if (!okay) // do some clean up.
}
In some cases you can do the same without an extra variable, depending on what the try block does.
A second option is a hack but also works.
try {
// do some work which might throw an exception
} catch (Throwable t) {
// do something with t.
Thread.currentThread().stop(t);
}
The stop(Throwable t) method doesn't stop the thread, instead it causes the thread to throw the exception provided in an unchecked way.
You can use Unsafe.throwException() with a bit of fiddling and there is a way to do this with Generics which I have forgotten.
If you are that concerned about getting your uninitialization to happen then you may want to just put that code into a finally block, as, if it should be called at some point, then you perhaps should always clean up.
I am leery of catching Throwable as some of the exceptions I want to handle, and some I just log, as, there is no use passing exceptions that the user can't do anything about, such as a NullPointerException.
But, you didn't show what SomeException is defined as, but if an OutOfMemoryException is thrown, your throwable will catch it, but it may not be the same type as SomeException so your wrapper will be needed in your sample function, at least when I look at the instanceOrUnchecked method.
You may want to write a unit test, try different classes of Exceptions and see what does or doesn't work as expected, so you can document the expected behavior.
An alternative is to have a factory which creates SomeException only if the cause is a checked exception:
public static SomeException throwException(String message, Throwable cause) throws SomeException {
unchecked(cause); //calls the method you defined in the question.
throw new SomeException(message, cause);
}
The reason why I put in the return value in the method is so that the client can do something like this:
catch (Throwable e) {
undoInitialize();
throw SomeException.throwException("message", e);
}
so that the compiler is fooled into not requiring a return after the catch statement if the method has a return type, but it still throws the exception if the client forgot to put the throw before the call to the factory method.
The disadvantage of this over your code is that it is less portable (it works for SomeException, but not for SomeOtherException), but that may be ok, because it won't be for every exception type that you need to have an undo initialize.
If it fits your use case you could put the unchecked call in the constructor of SomeException and have the logic available to all subclasses, but that would have to fit your specific project - it would not be a good idea in the general case as it would prevent wrapping runtime exceptions.
public SomeException(message, cause) {
super(message, unchecked(cause));
}
private static Throwable unchecked(Throwable cause) {
if (cause instanceof Error) throw (Error) cause;
if (cause instanceof RuntimeException) throw (RuntimeException) cause;
return cause;
}