java - 跳过try/catch block 以检查异常的Lambda

标签 java exception lambda java-8

由于我尝试提取在我的大多数项目中使用的一些常见的包装lambda例程,因此我能够创建CheckedFunction,它是PermeableFunction FunctionalInterface的子类,它绕过了try/catch块的需要。我已经在Windows(v1.8.0_251)/linux(v1.8.0_261)和其他几个在线编译器的Oracle jdks上进行了测试(不确定在那里使用了哪种实现)。
不确定这是否确实违反了规范或标准是否允许...根据我对docs的解释,这应该是不可能的:

More precisely, suppose that B is a class or interface, and A is a superclass or superinterface of B, and a method declaration n in B overrides or hides a method declaration m in A. Then:

  • If n has a throws clause that mentions any checked exception types, then m must have a throws clause, or a compile-time error occurs.
  • For every checked exception type listed in the throws clause of n, that same exception class or one of its supertypes must occur in the erasure (§4.6) of the throws clause of m; otherwise, a compile-time error occurs.
  • If the unerased throws clause of m does not contain a supertype of each exception type in the throws clause of n, a compile-time unchecked warning occurs.

这是我使用的示例代码:
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还允许像这样对可抛出对象进行阴影处理:
enter image description here
所以这是我的问题:
这是应该报告给实现者的问题,还是该标准强加的普遍问题?

最佳答案

你的方法

static <T, R, E extends Exception> CheckedFunction<T, R, E> from(WrappedFunction<T, R> wrappedFunction) {
    return wrappedFunction::applyChecked;
}
被我的Eclipse版本以及从9到14的所有JDK的javac拒绝了。只有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;
}
所有编译器都将接受它,但是会产生“未经检查”的警告。这是已知的事情。
您可以将示例简化为:
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;
    }
}
即使没有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;
    }
}
如前所述,这是众所周知的,但总的来说,您永远不应忽略“未经检查”的警告。

关于java - 跳过try/catch block 以检查异常的Lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63391917/

相关文章:

java - Python 服务器和 Java 客户端之间的连接被拒绝

node.js - 使用 AWS Lambda 函数和 Node.js 从 S3 存储桶中提取 zip 文件并上传到另一个存储桶

C# lambda 表达式 : How *Not* to Defer "Dereference"?

C++ 静态成员函数与 lambda 开销

Java:递归循环的组合,内部有不同的FOR循环;输出:FOR 循环索引

java - 如何替换 JasperDesign 中的 JRDesignBand?

java - 解释 Java extends ...& 尖括号中的语法

Ruby URL.parse 错误

java - 条目 fakeoutputdirectory=null 中出现错误 null 值?

python - 如何在 Python 中正确获取异常消息