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.
Related
Is there a way to have an Observable just throw an exception that occurs from within a function like flatMap()?
In Java, on a normal function, you can specify that it may throw an exception:
public void dangerousFunction() throws IOException {}
Within an Observable function like flatMap(), I can't seem to find a similar syntax. I can use a try/catch like this:
myObservable.flatMap(() -> {
try {
return dangerousFunction();
} catch (IOException e) {
return Observable.error(e);
}
});
Is there a cleaner method for writing that? If I have lots of maps and/or Observables, that winds up being a lot of try/catch blocks cluttering up my code.
The standard approach to dealing with exceptions in a RxJava map() method is propagate the exception by catch-and-throw. For example:
.map(b -> {
try {
...
} catch (IOException ex) {
// manual catch and throw
throw new RuntimeException(ex);
// or catch-and-throw using a built-in helper
throw Exceptions.propagate(e);
}
})
This can be get quite verbose when repeated across multiple map() calls so you could define a helper to wrap this behaviour e.g.
observable.map(RxMapWrapper.wrapAndThrow(new RxMapWrapper.Func1Wrapper<A, B>() {
#Override
public B call(A document) throws Exception {
// your map logic here ...
}
}))
public class RxMapWrapper {
public static <T, R> Func1<T, R> wrapAndThrow(Func1Wrapper<T, R> caughtFunction) {
return t -> {
try {
return caughtFunction.call(t);
} catch (Exception e) {
throw Exceptions.propagate(e);
}
};
}
public interface Func1Wrapper<T, R> extends Function {
R call(T t) throws Exception;
}
}
If you only want to return Observable.error(e) inside catch blocks, you don't need try/catch at all. Exception would go to downstream and .subscribe(,throwable) will catch it anyway.
If you want to return some other/default object when error occurred, try these operators: onErrorReturnItem, onErrorResumeNext, onErrorReturn. This would be cleaner.
Other option would be implementing this onErrorReturnItem mechanism into your methods itself instead of throwing Exception.
I'm trying to write a File and here is the code:
public static void writeFile(File f, int n) throws IOException{
//reads n teams which go to next phase
try(BufferedWriter writer = new BufferedWriter(new FileWriter(f))){
table.stream()
.sorted()
.limit(n)
.forEachOrdered(x->writer.write(x.getName()));
/*for(int i=0;i<n;i++){
writer.write(table.get(i).getName());
writer.newLine();
}*/ this if uncommented works great!
}catch (IOException e){
e.printStackTrace();
}
}
and I get this error when I try to compile:
Counter.java:123: error: unreported exception IOException; must be caught or declared to be thrown
.forEachOrdered(x->writer.write(x.getName()));
My doubt: Even if I declare the IOException in the method I am using the .forEachOrdered() I can't use it because the method which I define inside the .forEachOrdered() (which is a Consumer) doesn't declare it? I don't know if I am clear, but maybe you could infer something just looking at the code. Thanks.
Note: the table is a declared static list with Teams.
You could catch the IOException and rethrow it wrapped in an UncheckedIOException, like this:
.forEachOrdered(x-> {
try{
writer.write(x.getName()));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
The stream will not continue processing if an IOException is thrown.
Outside of the stream, you should then change your catch to
} catch (IOException | UncheckedIOException e) {
e.printStackTrace();
}
You might create convenience functional types that take care of the try/catch for you, something like
#FunctionalInterface
public interface CheckedIOConsumer<T> {
void accept(T t) throws IOException;
static <T> Consumer<T> toUnchecked(CheckedIOConsumer<T> consumer) {
return t -> {
try {
consumer.accept(t);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
};
}
}
which would make your terminal function
.forEachOrdered(toUnchecked(x -> writer.write(x.getName())));
The problem is that the signature for forEachOrdered requires a Consumer and a Consumer does not declare that its accept method can throw any checked exceptions.
JLS 11.2.3 says:
It is a compile-time error if a lambda body can throw some exception class E when E is a checked exception class and E is not a subclass of some class declared in the throws clause of the function type targeted by the lambda expression.
Therefore, the IOException must be caught by the lambda itself. The recommended solutions are:
catch and handle it within the lambda, or
catch it in the lambda and rethrow it wrapped in an unchecked exception, then catch / handle the wrapped exception at the outer level. #Hank D's answer illustrates this.
The problem with handling the IOException within the lambda is that the "for each" will continue running.
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));
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 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.