Java8泛型+;使用lambda表达式时出现异常编译时错误

Java8泛型+;使用lambda表达式时出现异常编译时错误,java,generics,lambda,java-8,Java,Generics,Lambda,Java 8,几天前,我开始重构一些代码以使用新的Java8Streams库。不幸的是,我在使用一个方法执行Stream::map时遇到了编译时错误,该方法被声明为抛出一个泛型E,该泛型E被进一步指定为RuntimeException 有趣的是,当我切换到使用方法引用时,编译时错误消失了 这是一个bug,还是我的方法引用与lambda表达式不等价 (另外,我知道我可以用Parameter::execute替换p->p.execute(foo)。我的实际代码中有execute方法的其他参数) 错误消息 Err

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

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

这是一个bug,还是我的方法引用与lambda表达式不等价

(另外,我知道我可以用Parameter::execute替换p->p.execute(foo)。我的实际代码中有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.
    }

}

代码

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.
    }

}
import java.util.ArrayList;
导入java.util.List;
公共类JavaBugTest
{
接口AbleToThrowException
{
}
界面参数{
公共对象执行(AbleToThrowException algo)抛出E;
}
接口ThrowRuntimeException扩展了AbleToThrowException
{
}
静态ThrowsRuntimeException-foo;
公共静态对象手册lambda(参数p)
{
返回p.execute(foo);
}
公共静态void main(字符串[]args)
{
List params=new ArrayList();
params.stream().map(p->p.execute(foo));//给出编译时错误。
params.stream().map(JavaBugTest::manualLambda);//工作正常。
}
}

系统设置

  • 操作系统:Windows x64
  • Java编译器版本:Oracle JDK 1.8.0_11
  • IDE:Intellij

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

params.stream().map(p->p.execute(foo));//给出一个编译时错误。
如果没有显式类型参数,JDK编译器似乎无法从调用上下文推断类型参数,尽管它应该这样做。这是一个bug,应该这样报告。我现在已经报告了,当我有新的细节时,我会用新的细节更新这个问题


您使用的是哪种编译器?我对Eclipse的编译器没有任何问题。但我用甲骨文的。@SotiriosDelimanolis我的IDE是Intellij。但是,Intellij声称javac正在进行实际编译:“信息:使用JavaC1.8.0_11编译java源代码”。不过,我想我应该尝试从命令行手动编译。不过,我认为这是编译器中的一个错误。请注意,
manualLambda
案例之所以有效,是因为
manualLambda
方法没有声明任何异常。@SotiriosDelimanolis Eclipse为两个调用生成的字节码是相同的。我同意这可能是javac中的一个bug。我想几个月前在JAX2014会议上有人已经提到了这个bug,并且已经发布了bugreport的链接——但我现在找不到它。但是在某个地方有一个列表描述了eclipse编译器和javac在Java8特性方面的差异。@mschenk74您同时找到错误报告了吗?我们也遇到了这个错误,希望查看状态。我还没有找到我提到的错误报告。