由于我试图提取一些常见的 Package lambda例程(我在大多数项目中使用这些例程),我已经能够创建CheckedFunction
,PermeableFunction
FunctionalInterface的子类,它绕过了try/catch块的需要。我已经在Oracle jdks for windows上测试过了(v1.8.0_251)/linux(v1.8.0_261)和其他几个在线编译器(不确定那里使用的是哪个实现)。
不确定这是否真的违反了规范或者是标准允许的......根据我对文档的解释,这是不可能的:
更准确地说,假设B是一个类或接口,A是B的超类或超接口,B中的方法声明n覆盖或隐藏了A中的方法声明m,则:
- 如果n有一个throws子句提到了任何检查过的异常类型,那么m必须有一个throws子句,否则会发生编译时错误。
- 对于列在n的throws子句中的每一个被检查的异常类型,相同的异常类或其超类型之一必须出现在m的throws子句的擦除(§4.6)中;否则会发生编译时错误。
- 如果m的未删除throws子句不包含n的throws子句中每个异常类型的超类型,则会出现编译时未检查警告。
下面是我使用的示例代码:
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.function.Function;
public class Main {
public static void main(String[] args) {
PermeableFunction<Path, Long> function = PermeableFunction.from(Files::size);
Path doesNotExist = Paths.get("/does/not/exist");
// function.apply(doesNotExist); -> throws WrappedException
function.applyChecked(doesNotExist); // throws NoSuchFileException without the need of a try/catch block!
}
}
interface PermeableFunction<T,R> extends CheckedFunction<T, R, RuntimeException> {
static <T, R> PermeableFunction<T, R> from(WrappedFunction<T, R> wrappedFunction) {
return CheckedFunction.<T,R, RuntimeException>from(wrappedFunction)::applyChecked;
}
}
interface CheckedFunction<T, R, E extends Exception> extends WrappedFunction<T, R> {
@Override
R applyChecked(T t) throws E;
static <T, R, E extends Exception> CheckedFunction<T, R, E> from(WrappedFunction<T, R> wrappedFunction) {
return wrappedFunction::applyChecked;
}
}
interface WrappedFunction<T, R> extends Function<T, R> {
R applyChecked(T t) throws Exception;
@Override
default R apply(T t) {
try {
return applyChecked(t);
} catch (Exception e) {
throw new WrappedException(e);
}
}
}
class WrappedException extends RuntimeException {
public WrappedException(Throwable cause) {
super(cause);
}
}
CheckedFunction还允许隐藏throwable,如下所示:
所以我的问题是:
这是应该向实现者报告的事情,还是标准强加的一般问题?
1条答案
按热度按时间b4lqfgs41#
你的方法
我的Eclipse版本以及从9到14的所有JDK的
javac
都拒绝了它。只有JDK 8接受它,所以这是一个bug,但不值得报告,因为较新的版本没有它。也就是说,通过泛型类型系统破坏异常检查是可能的。
将方法更改为
所有的编译器都会接受它,但是会产生一个“未检查”的警告。2这是已知的。
您可以将示例简化为:
即使没有lambda表达式,也有几种可能的变体。它所需要的只是一个使用类型参数的
throws
声明和一个关于该类型参数的未检查操作。例如
正如所说,这是众所周知的,外卖是,你永远不应该忽视“未检查”的警告。