dbl*_*dbl 5 java lambda exception java-8
由于我试图提取一些我在大多数项目中使用的常见包装 lambda 例程,我已经能够创建CheckedFunction,由PermeableFunctionFunctionalInterface子类化,绕过 try/catch 块的需要。我已经在用于 windows(v1.8.0_251)/linux(v1.8.0_261) 和其他几个在线编译器的 Oracle jdks 上测试了它(不确定那里使用了哪个实现)。
不确定这是否真的违反了规范或者是标准允许的......根据我对文档的解释,这应该是不可能的:
更准确地说,假设 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);
}
}
Run Code Online (Sandbox Code Playgroud)
CheckedFunction 还允许像这样对 throwable 进行阴影处理:
所以这是我的问题:
这是应该报告给实施者的事情还是标准强加的一般问题?
你的方法
static <T, R, E extends Exception> CheckedFunction<T, R, E> from(WrappedFunction<T, R> wrappedFunction) {
return wrappedFunction::applyChecked;
}
Run Code Online (Sandbox Code Playgroud)
被我的 Eclipse 版本以及javac从 9 到 14 的所有 JDK拒绝。只有 JDK 8 接受它,所以这是一个错误,但不值得报告,因为较新的版本没有它。
也就是说,通过泛型类型系统颠覆异常检查是可能的。
当您将方法更改为
static <T, R, E extends Exception> CheckedFunction<T, R, E> from(WrappedFunction<T, R> wrappedFunction) {
return (CheckedFunction)(CheckedFunction<T, R, Exception>)wrappedFunction::applyChecked;
}
Run Code Online (Sandbox Code Playgroud)
所有编译器都会接受它,但会产生“未经检查”的警告。这是众所周知的事情。
您可以将示例简化为:
public class Main {
public static void main(String[] args) {
CheckedFunction<Path, Long, RuntimeException> function = (CheckedFunction)
(CheckedFunction<Path, Long, IOException>)Files::size;
Path doesNotExist = Paths.get("/does/not/exist");
function.applyChecked(doesNotExist); // throws NoSuchFileException without the need of a try/catch block!
}
interface CheckedFunction<T, R, E extends Exception> {
R applyChecked(T t) throws E;
}
}
Run Code Online (Sandbox Code Playgroud)
即使没有 lambda 表达式,也有几种可能的变化。它所需要的只是throws使用类型参数的声明和有关此类型参数的未经检查的操作。
例如
public class Main {
public static void main(String[] args) {
try {
Files.size(Paths.get("/does/not/exist"));
}
catch(IOException ex) {
doThrow(ex); // throws undeclared IOException
}
}
static <T extends Throwable> void doThrow(Throwable t) throws T {
throw (T)t;
}
}
Run Code Online (Sandbox Code Playgroud)
如前所述,这是众所周知的,要点是,您永远不应该忽略“未经检查”的警告。
| 归档时间: |
|
| 查看次数: |
146 次 |
| 最近记录: |