使用 lambda 表达式时 Java 8 泛型 + 异常编译时错误

标签 java generics lambda java-8

几天前,我开始重构一些代码以使用新的 Java 8 Streams 库。不幸的是,我在执行 Stream::map 时遇到了编译时错误,该方法被声明为抛出一个泛型 E,该泛型 E 进一步指定为 RuntimeException。

有趣的是,当我切换到使用方法引用时,编译时错误消失了。

这是一个错误,还是我的方法引用不等同于我的 lambda 表达式?

(此外,我知道我可以将 p->p.execute(foo) 替换为 Parameter::execute。我的实际代码具有执行方法的附加参数)。


错误信息

Error:(32, 43) java: unreported exception E; must be caught or declared to be thrown

代码

import java.util.ArrayList;
import java.util.List;


public class JavaBugTest
{
    interface AbleToThrowException<E extends Exception>
    {
    }

    interface Parameter {
        public <E extends Exception> Object execute(AbleToThrowException<E> algo) throws E;
    }

    interface ThrowsRuntimeException extends AbleToThrowException<RuntimeException>
    {
    }

    static ThrowsRuntimeException foo;


    public static Object manualLambda(Parameter p)
    {
        return p.execute(foo);
    }

    public static void main(String[] args)
    {
        List<Parameter> params = new ArrayList<>();
        params.stream().map(p -> p.execute(foo)); // Gives a compile time error.
        params.stream().map(JavaBugTest::manualLambda); // Works fine.
    }

}

系统设置

  • 操作系统:Windows x64
  • Java编译器版本:Oracle JDK 1.8.0_11
  • 集成开发环境:Intellij

最佳答案

一个非常简单的解决方案是为 Parameter#execute(..) 显式提供类型参数。

params.stream().map(p -> p.<RuntimeException>execute(foo)); // Gives a compile time error.

如果没有显式类型参数,JDK 编译器似乎无法从调用上下文中推断出类型参数,尽管它应该如此。这是一个错误,应该这样报告。我现在已经报告了它,并会在我有新的详细信息时更新这个问题。

Bug Report

关于使用 lambda 表达式时 Java 8 泛型 + 异常编译时错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24986279/

相关文章:

java - 收到的 UDP 消息长度不正确

java - 处理 2.0 中 ArrayList<byte> 的语法错误

typescript - 嵌套的 Typescript 泛型

c# - 将通用方法参数转换为特定类型

c# - lambda 语法中的 linq 类型声明

java - 为什么 Query、TermQuery 等在 Lucene 4.0 中不再实现 Serialized?

java - IMDG (Hazelcast) 如何加强数据一致性

swift - 如何在 Swift 中使用函数参数消除对泛型函数的调用的歧义?

java - 使用通用 ID 扩展基本实体的实体的 ID 映射

c++ - unique_ptr 和默认可构造指针