有什么方法可以在块外从 foreach 的消费者那里捕获 RuntimeException 吗?
Is there any way to catch a RuntimeException from a foreach's consumer, outside of the block?
我有一些代码(还有一些嵌套的 forEach's
和 streams
):
void process() throws RuntimeException
{
try {
ArrayList<Integer> ints = new ArrayList<>();
ints.add(1);
ints.add(2);
ints.add(3);
ints.forEach(e -> {
System.out.println(e);
throw new RuntimeException("RuntimeException");
});
}
catch (RuntimeException rex)
{
rex.printStackTrace();
throw rex; // throw it up, and up, and up...
}
}
它不起作用,因为 foreach's
Consumer's
accept()
默认情况下不会抛出异常。即使它有 throws
签名 - 我无法在块外捕获它。
我需要做的是从 foreach()
方法本身捕获异常。
有没有什么方法可以在没有一些外部方法的情况下实现这一点,比如
void handleException(RuntimeException ex){ ... }
并在每个 forEach()'s
try/catch ?
中调用它
我发现这个问题是错误的 - 它实际上适用于 RuntimeException
。
对于已检查的异常,有一个工作代码:
package Exporter;
import java.util.function.Consumer;
import java.util.function.Function;
public final class LambdaExceptions {
@FunctionalInterface
public interface Consumer_WithExceptions<T, E extends Exception> {
void accept(T t) throws E;
}
@FunctionalInterface
public interface Function_WithExceptions<T, R, E extends Exception> {
R apply(T t) throws E;
}
/**
* .forEach(rethrowConsumer(name -> System.out.println(Class.forName(name))));
*/
public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) throws E {
return t -> {
try {
consumer.accept(t);
} catch (Exception exception) {
throwActualException(exception);
}
};
}
/**
* .map(rethrowFunction(name -> Class.forName(name))) or .map(rethrowFunction(Class::forName))
*/
public static <T, R, E extends Exception> Function<T, R> rethrowFunction(Function_WithExceptions<T, R, E> function) throws E {
return t -> {
try {
return function.apply(t);
} catch (Exception exception) {
throwActualException(exception);
return null;
}
};
}
@SuppressWarnings("unchecked")
private static <E extends Exception> void throwActualException(Exception exception) throws E {
throw (E) exception;
}
}
它就像一个魅力:
void process() throws RuntimeException
{
try {
ArrayList<Integer> ints = new ArrayList<>();
ints.add(1);
ints.add(2);
ints.add(3);
ints.forEach(LambdaExceptions.rethrowConsumer(e -> {
System.out.println(e);
throw new RuntimeException("RuntimeException");
}));
}
catch (RuntimeException rex)
{
System.out.println("Got first exception");
rex.printStackTrace();
throw rex;
}
}
我有一些代码(还有一些嵌套的 forEach's
和 streams
):
void process() throws RuntimeException
{
try {
ArrayList<Integer> ints = new ArrayList<>();
ints.add(1);
ints.add(2);
ints.add(3);
ints.forEach(e -> {
System.out.println(e);
throw new RuntimeException("RuntimeException");
});
}
catch (RuntimeException rex)
{
rex.printStackTrace();
throw rex; // throw it up, and up, and up...
}
}
它不起作用,因为 foreach's
Consumer's
accept()
默认情况下不会抛出异常。即使它有 throws
签名 - 我无法在块外捕获它。
我需要做的是从 foreach()
方法本身捕获异常。
有没有什么方法可以在没有一些外部方法的情况下实现这一点,比如
void handleException(RuntimeException ex){ ... }
并在每个 forEach()'s
try/catch ?
我发现这个问题是错误的 - 它实际上适用于 RuntimeException
。
对于已检查的异常,有一个工作代码:
package Exporter;
import java.util.function.Consumer;
import java.util.function.Function;
public final class LambdaExceptions {
@FunctionalInterface
public interface Consumer_WithExceptions<T, E extends Exception> {
void accept(T t) throws E;
}
@FunctionalInterface
public interface Function_WithExceptions<T, R, E extends Exception> {
R apply(T t) throws E;
}
/**
* .forEach(rethrowConsumer(name -> System.out.println(Class.forName(name))));
*/
public static <T, E extends Exception> Consumer<T> rethrowConsumer(Consumer_WithExceptions<T, E> consumer) throws E {
return t -> {
try {
consumer.accept(t);
} catch (Exception exception) {
throwActualException(exception);
}
};
}
/**
* .map(rethrowFunction(name -> Class.forName(name))) or .map(rethrowFunction(Class::forName))
*/
public static <T, R, E extends Exception> Function<T, R> rethrowFunction(Function_WithExceptions<T, R, E> function) throws E {
return t -> {
try {
return function.apply(t);
} catch (Exception exception) {
throwActualException(exception);
return null;
}
};
}
@SuppressWarnings("unchecked")
private static <E extends Exception> void throwActualException(Exception exception) throws E {
throw (E) exception;
}
}
它就像一个魅力:
void process() throws RuntimeException
{
try {
ArrayList<Integer> ints = new ArrayList<>();
ints.add(1);
ints.add(2);
ints.add(3);
ints.forEach(LambdaExceptions.rethrowConsumer(e -> {
System.out.println(e);
throw new RuntimeException("RuntimeException");
}));
}
catch (RuntimeException rex)
{
System.out.println("Got first exception");
rex.printStackTrace();
throw rex;
}
}