We use JUnit 3 at work and there is no ExpectedException annotation. I wanted to add a utility to our code to wrap this:
try {
someCode();
fail("some error message");
} catch (SomeSpecificExceptionType ex) {
}
So I tried this:
public static class ExpectedExceptionUtility {
public static <T extends Exception> void checkForExpectedException(String message, ExpectedExceptionBlock<T> block) {
try {
block.exceptionThrowingCode();
fail(message);
} catch (T ex) {
}
}
}
However, Java cannot use generic exception types in a catch block, I think.
How can I do something like this, working around the Java limitation?
Is there a way to check that the ex variable is of type T?
You could pass the Class object in and check that programatically.
public static <T extends Exception> void checkForException(String message,
Class<T> exceptionType, ExpectedExceptionBlock<T> block) {
try {
block.exceptionThrowingCode();
} catch (Exception ex) {
if ( exceptionType.isInstance(ex) ) {
return;
} else {
throw ex; //optional?
}
}
fail(message);
}
//...
checkForException("Expected an NPE", NullPointerException.class, //...
I'm not sure if you'd want the rethrow or not; rethrowing would equally fail/error the test but semantically I wouldn't, since it basically means "we didn't get the exception we expected" and so that represents a programming error, instead of a test environment error.
I understand the impulse to try to simplify your exception-test idiom, but seriously: don't. Every possible choice you'll come up with is a cure that's worse than the disease. Especially JUnit 4's #ExpectedException nonsense! It is a too-clever frameworky solution, requiring everyone to learn how it works, as opposed to a plain self-evident bit of regular Java code. Worse, it gives you no way to wrap only the part of your test that you expect to throw the exception, so if an earlier setup step throws that same exception, your test will pass even though your code is broken.
I could write a long diatribe about this here (I'm sorry for not having enough time to), as we've had a lengthy discussion of this issue among Java engineers here at Google, and the consensus was that none of these crazy solutions are worthwhile. Get used to try/catch, it's really not that bad.
Catch clause with type parameter is not possible:
http://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#cannotCatch
Well, you could just catch Exception and rethrow if it's not an expected Exception. Though good coding practice usually dictates that the success path of code should not be defined by an Exception, so you might want to rethink your design.
Generics are not types. They are not templates. They are compile time type checks, in Java. Exception blocks catch on type. You can catch(Exception e) or even catch(Throwable e) and then cast as needed.
You can also use an IDE that supports live template ( like IntellJ IDEA for instance ) and assign a shortcut like ee -> [tab] that inserts the try/catch/ignore for your and let you type the correct one.
#FunctionalInterface
public interface ThrowingConsumer<T, E extends Exception> {
void accept(T t) throws E;
}
public static <T, E extends Exception> Consumer<T> errConsumerWrapper(ThrowingConsumer<T, E> throwingConsumer,
Class<E> exceptionClass,
Consumer<E> exceptionConsumer) {
return i -> {
try {
throwingConsumer.accept(i);
} catch (Exception ex) {
try {
exceptionConsumer.accept(exceptionClass.cast(ex));
} catch (ClassCastException ccEx) {
throw new RuntimeException(ex);
}
}
};
}
Usage example
Stream.of("a").forEach(errConsumerWrapper(i -> Integer.parseInt(i),
NumberFormatException.class,
Throwable::printStackTrace));
Related
Given a function that might throw:
public static int f() throws Exception {
// do something
}
Is there any way this code:
public static int catchF() throws Exception {
try {
return f();
} catch (Exception ex) {
throw ex;
}
}
is any different to calling f directly? I.e. could the caller detect the difference by inspecting the exception? Is there any discernible overhead in using catchF instead of f?
If there is no difference, can compilers, or the JVM, optimise a call to catchF into a direct call to f?
While this might seem like a strange thing to do, the use case would be to re-introduce an exception at the type level after earlier hiding it:
class Test {
// Hide the exception.
public static <X extends Exception, T> T throwUnchecked(Exception ex) throws X {
throw (X) ex;
}
// Interface for functions which throw.
interface Throws<T, R, X extends Exception> {
R apply(T t) throws X;
}
// Convert a function which throws a visible exception into one that throws a hidden exception.
public static <T, R, X extends Exception> Function<T, R> wrap(Throws<T, R, X> thrower) {
return t -> {
try {
return thrower.apply(t);
} catch(Exception ex) {
return throwUnchecked(ex);
}
};
}
// Unhide an exception.
public static <R, X extends Exception> R unwrap(Supplier<R> supp) throws X {
try {
return supp.get();
} catch (Exception ex) {
throw (X)ex;
}
}
public static Stream<Integer> test(Stream<String> ss) throws NumberFormatException {
return Test.<Stream<Integer>, NumberFormatException>unwrap(
() -> ss.map(wrap(Integer::parseInt))
);
}
public static void main(String[] args) throws NumberFormatException {
final List<Integer> li = test(Arrays.stream(new String[]{"1", "2", "3"})).collect(toList());
System.out.println(li);
}
}
The intent is to wrap functions that throw exception into ones where the exception is hidden at the type level. This makes the exceptions usable for example with streams.
is any different to calling f directly?
No.
I.e. could the caller detect the difference by inspecting the exception?
No, because you're not constructing a new exception at this point. The stack trace was constructed at the point where the new WhateverException(...) was invoked (not where the throw was, although they are often in the same place).
Typically, you rethrow a caught exception if you need to do some cleanup as a result of the exception:
try {
// ...
} catch (SomeException e) {
// Clean up resources.
throw e;
}
The fact that something happened as the call stack was unwound is neither visible nor relevant to the caller.
A quick demo can show that the stack traces are identical whether the exception is caught and rethrown or simply allowed to propagate.
Is there any discernible overhead in using catchF instead of f?
The overhead of constructing the exception will far outweight any overhead of this redundant construct.
An exception handler that simply rethrows and does not affect the known types of the exceptions has absolutely no semantic effect.
In theory, then, compilers or the JVM could optimize the try-catch out. In practice, I doubt that they do, because such code should be rare and not on hot paths (exceptions should never be); it's probably not worth the effort to implement such an optimization.
We use JUnit 3 at work and there is no ExpectedException annotation. I wanted to add a utility to our code to wrap this:
try {
someCode();
fail("some error message");
} catch (SomeSpecificExceptionType ex) {
}
So I tried this:
public static class ExpectedExceptionUtility {
public static <T extends Exception> void checkForExpectedException(String message, ExpectedExceptionBlock<T> block) {
try {
block.exceptionThrowingCode();
fail(message);
} catch (T ex) {
}
}
}
However, Java cannot use generic exception types in a catch block, I think.
How can I do something like this, working around the Java limitation?
Is there a way to check that the ex variable is of type T?
You could pass the Class object in and check that programatically.
public static <T extends Exception> void checkForException(String message,
Class<T> exceptionType, ExpectedExceptionBlock<T> block) {
try {
block.exceptionThrowingCode();
} catch (Exception ex) {
if ( exceptionType.isInstance(ex) ) {
return;
} else {
throw ex; //optional?
}
}
fail(message);
}
//...
checkForException("Expected an NPE", NullPointerException.class, //...
I'm not sure if you'd want the rethrow or not; rethrowing would equally fail/error the test but semantically I wouldn't, since it basically means "we didn't get the exception we expected" and so that represents a programming error, instead of a test environment error.
I understand the impulse to try to simplify your exception-test idiom, but seriously: don't. Every possible choice you'll come up with is a cure that's worse than the disease. Especially JUnit 4's #ExpectedException nonsense! It is a too-clever frameworky solution, requiring everyone to learn how it works, as opposed to a plain self-evident bit of regular Java code. Worse, it gives you no way to wrap only the part of your test that you expect to throw the exception, so if an earlier setup step throws that same exception, your test will pass even though your code is broken.
I could write a long diatribe about this here (I'm sorry for not having enough time to), as we've had a lengthy discussion of this issue among Java engineers here at Google, and the consensus was that none of these crazy solutions are worthwhile. Get used to try/catch, it's really not that bad.
Catch clause with type parameter is not possible:
http://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#cannotCatch
Well, you could just catch Exception and rethrow if it's not an expected Exception. Though good coding practice usually dictates that the success path of code should not be defined by an Exception, so you might want to rethink your design.
Generics are not types. They are not templates. They are compile time type checks, in Java. Exception blocks catch on type. You can catch(Exception e) or even catch(Throwable e) and then cast as needed.
You can also use an IDE that supports live template ( like IntellJ IDEA for instance ) and assign a shortcut like ee -> [tab] that inserts the try/catch/ignore for your and let you type the correct one.
#FunctionalInterface
public interface ThrowingConsumer<T, E extends Exception> {
void accept(T t) throws E;
}
public static <T, E extends Exception> Consumer<T> errConsumerWrapper(ThrowingConsumer<T, E> throwingConsumer,
Class<E> exceptionClass,
Consumer<E> exceptionConsumer) {
return i -> {
try {
throwingConsumer.accept(i);
} catch (Exception ex) {
try {
exceptionConsumer.accept(exceptionClass.cast(ex));
} catch (ClassCastException ccEx) {
throw new RuntimeException(ex);
}
}
};
}
Usage example
Stream.of("a").forEach(errConsumerWrapper(i -> Integer.parseInt(i),
NumberFormatException.class,
Throwable::printStackTrace));
I have a method that deletes some files:
void deepDelete(Path root) {
Files.walk(root)
.filter(p -> !Files.isDirectory(p))
.forEach(p -> { try { Files.delete(p); }
catch (IOException e) { /* LOG */ }
});
}
The try/catch block reduces the readability of the operation, especially vs. using a method reference:
void deepDelete(Path root) throws IOException {
Files.walk(root)
.filter(p -> !Files.isDirectory(p))
.forEach(Files::delete); //does not compile
}
Unfortunately that code does not compile.
Is there a way to apply an action that throws checked exceptions in a terminal operation and simply "rethrow" any exceptions?
I understand that I could write a wrapper that transforms the checked exception into an unchecked exception but I would rather stick to methods in the JDK if possible.
As far as I can tell: no. I use this techempower article as my java8 guide, and it's pretty explicit (see the section headed "Exception transparency").
If you declare this method:
#SuppressWarnings("unchecked")
static <T extends Throwable> RuntimeException sneakyThrow(Throwable t) throws T {
throw (T)t;
}
Then you can do:
try {
Files.delete(p);
} catch (IOException e) {
throw sneakyThrow(e);
}
This bypasses the checked exception rules and throws the raw IOException without wrapping, although you still have to catch it & rethrow. I'm not saying this is a good idea, but it's an idea.
I have designed a uploaded file handling as follow:
The UploadFileHandler is the main class providing checking methods.
public class UploadedFileHandler {
public static void handleUploadedFile(String fileName) {
try {
checkFile(fileName);
} catch (BadUploadedFileException ex) {
deleteFile(fileName);
}
}
private static void checkFile(String fileName) {
new UploadedFileChecker(fileName).check();
}
private static void deleteFile(String fileName) {
//...code to delete the file.
}
}
And the UploadedFileChecker do the checking.
public class UploadedFileChecker {
private String fileName;
public UploadedFileChecker(String fileName) {
this.fileName = fileName;
}
public void check() throws BadUploadedFileException {
checkFileFormat();
scanVirus();
}
private void checkFileFormat() {
// if file format unsupported
throw new BadUploadedFileException();
}
private void scanVirus() {
// if contains virus
throw new BadUploadedFileException();
}
}
And the BadUploadedFileException is declared as follow:
public class BadUploadedFileException extends RuntimException {
}
I let it extend RuntimeException because it makes the code in UploadedFileChecker clean, but doing this make it an unchecked exception. Thus, the catch in handleUploadedFile is inapproriate since we should not catch unchecked exceptions.
My question is, should I catch the BadUploadedFileException or make it extends Exception and append "throws BadUploadedFileException" to every method of UploadedFileChecker.
Exceptions should be used for exceptional conditions. Things that you don't expect to happen.
You shouldn't use them for conditional logic.
Josh Bloch outlines that specifically in his book, which is quite good and a must-have IMHO:
http://java.sun.com/docs/books/effective/
since we should not catch unchecked exceptions.
There is no such rule. You catch any exceptions whenever you know what to do with it.
However, one must never catch Errors!
I think you'd be better off making check() return a boolean.
I believe that'll make the code look cleaner, and like Brian said- exceptions aren't really for logic- they're for when something goes unexpectedly wrong.
are you going to do anything if you get an exception? If not, let it bubble. If you are then you can certainly catch an uncheck exception.
Personally, I think it should be a checked exception. You should prob. throw it from each file handling method and catch it in UploadedFileHandler, handling it appropriately, if you need different handling logic then split BadUploadedFileException into a number of different types of exceptions.
More information on checked and unchecked exceptions here.
The last option would be preferable. I don't think it makes the code much harder to read, and at least you (and your colleagues in upcoming versions) will be remembering to handle it.
Besides that, it is certainly not forbidden to catch Exceptions derived from RuntimeException. Catching RuntimeException or Exception on the other hand should only be done in main methods and suchlike (it could be an OutOfMemoryException!).
If you use explicit RuntimeExceptions, don't use a "throws" keyword in the method specification but do include them in the JavaDoc if they seem important.
I want a method that can throw any Throwable including sub classes of Exception. Ive got something that takes an exception, stashes it in a thread local, then invokes a class.newInstance. That class ctor declares that it throws Exception then takes the threadlocal and throws it. Problem is it does not work for the two declared Exceptions thrown by Class.newInstance() namely IllegalAccessException and InstantiationException.
Im guessing any other method using some sun.* class is just a hack and not really reliable.
Wrapping is not an option because that means catchers are catching a diff type and that's just too simple and boring...
static public void impossibleThrow(final Throwable throwable) {
Null.not(throwable, "throwable");
if (throwable instanceof RuntimeException) {
throw (RuntimeException) throwable;
}
if (throwable instanceof Error) {
throw (Error) throwable;
}
try {
THROW.set((Exception) throwable);
THROWER.newInstance();
} catch (final InstantiationException screwed) {
throw new Error(screwed);
} catch (final IllegalAccessException screwed) {
throw new Error(screwed);
} finally {
THROW.remove();
}
}
private final static Class<Impossible> THROWER = Impossible.class;
private final static ThreadLocal<Exception> THROW = new ThreadLocal<Exception>();
static private class Impossible {
#SuppressWarnings("unused")
public Impossible() throws Exception {
throw THROW.get();
}
}
From Java Puzzlers (puzzle 43):
public static void impossibleThrow(Throwable t)
{
Thread.currentThread().stop(t); // Deprecated method.
}
The book shows other methods of achieving the same problem, one is a simplified version of yours, the other exploits generic type erasure to throw any Throwable where an Error is expected.
If you want an Exception to bubble up through code not expecting that exception then just wrap it in a RuntimeException
} catch (RuntimeException e) {
throw e; // only wrap if needed
} catch (Exception e) {
throw new RuntimeException("FOO went wrong", e);
}
Remember to let the message be informative. Some day you will have to fix a bug based only on the information in the stack trace.
Wrapping an exception inside a RuntimeException (as suggested by Thorbjørn) is the way to go. However, you usually want to maintain the stacktrace of the original excpetion. Here's how:
public static void rethrow(final Throwable t)
{
if(t instanceof RuntimeException)
throw (RuntimeException) t;
RuntimeException e = new RuntimeException(t);
e.setStackTrace(t.getStackTrace());
throw e;
}
I patched javac to remove the error, compiled impossibleThrow(), renamed the source file to something that does not end in .java (which forces the next compile to use the existing .class) and used that.
There is some validity for this question as a debugging tool. Suppose you are working with some code that may have failed and you see that it (perhaps) catches certain exceptions and (perhaps) throws certain exceptions. You suspect that an unexpected exception was not caught. However, the underlying code/system is too complex and the bug is too intermittent to allow you to step through in the debugger. It can be usefull to add the throwing of an exception without changing the method in any other way. In this case, wrapping the exception with a RuntimeException would not work, because you want the calling methods to behave normally.