当实例作为其超级接口传递时,Java 8默认实现不可用

当实例作为其超级接口传递时,Java 8默认实现不可用,java,java-8,Java,Java 8,调用一个方法时,我收到一个AbstractMethodError,我认为该方法在目标实例中应该有一个默认实现 我用三个参数创建了一个函数接口,但也派生自java.util.function.function,并提供了函数的默认实现#apply(…)。然后,我使用3参数lambda表达式创建接口的实例。三参数方法和函数#apply(..)在创建的实例中都可以正常工作 当我将创建的实例传递给一个需要我的接口的方法时,我可以从该方法中调用函数#apply(..),它工作得很好 但是,当我将实例传递给一

调用一个方法时,我收到一个
AbstractMethodError
,我认为该方法在目标实例中应该有一个默认实现

我用三个参数创建了一个函数接口,但也派生自
java.util.function.function
,并提供了
函数的默认实现#apply(…)
。然后,我使用3参数lambda表达式创建接口的实例。三参数方法和
函数#apply(..)
在创建的实例中都可以正常工作

当我将创建的实例传递给一个需要我的接口的方法时,我可以从该方法中调用
函数#apply(..)
,它工作得很好

但是,当我将实例传递给一个需要
函数的方法时,当我尝试调用
函数时,我会收到
AbstractMethodError

似乎我对默认方法如何以及何时绑定到实例缺乏理解。我做错了什么

证明:

package spike;

import java.util.function.BiFunction;
import java.util.function.Function;

public class ReductionProblem {

    interface F3<T, U, V, R> extends Function<T, BiFunction<U, V, R>> {

        default BiFunction<U, V, R> apply(final T t) {
            return (U u, V v) -> apply(t, u, v);
        }

        R apply(T t, U u, V v);

    }

    private static <T, U, V, R> BiFunction<U, V, R> workingReduce(
            F3<T, U, V, R> f, T t) {
        return f.apply(t);
    }

    private static <T, U, V, R> BiFunction<U, V, R> brokenReduce(
            Function<T, BiFunction<U, V, R>> f, T t) {
        return f.apply(t);
    }

    public static void main(String[] args) {

        /*
         * Object is instantiated here, right? So, Function#apply(Integer)
         * should be defined and ready to go.
         */
        final F3<Integer, Integer, String, Integer> f3 = (a, b, c) -> a * b
                * c.length();

        final Integer a = 3, b = 13;
        final String c = "see";

        final Integer expected = a * b * c.length();

        Integer v1 = f3.apply(a, b, c);
        display("invoke with 3", expected, v1);

        /*
         * It appears that f3 can indeed behave as a Function<Integer,
         * BiFunction<>> ...
         */
        Integer v2 = f3.apply(a).apply(b, c);
        display("invoke with 1 then 2", expected, v2);

        /*
         * From inside a method, no problem...
         */
        Integer v3 = workingReduce(f3, a).apply(b, c);
        display("invoke with 1 inside special reducer", expected, v3);

        /*
         * But when passed explicitly as a Function, AbstractMethodError is
         * thrown from inside the reduction method. So, it seems that the
         * instantiation of the object with the default method implementation
         * does not occur where I am supposing it does.
         */
        Integer v4 = brokenReduce(f3, a).apply(b, c);
        display("invoke with 1 inside general reducer", expected, v4);

    }

    private static void display(String label, Object expected, Object actual) {

        System.out.println(label + ":"
                + (actual.equals(expected) ? "pass" : "fail"));

    }

}
封装尖峰;
导入java.util.function.BiFunction;
导入java.util.function.function;
公共类约简问题{
接口F3扩展函数{
默认双功能应用(最终T){
返回(U,V)->应用(t,U,V);
}
R应用(T,U,V);
}
专用静态双功能workingReduce(
F3(f,T){
返回f.apply(t);
}
专用静态双功能中断还原(
函数f,T){
返回f.apply(t);
}
公共静态void main(字符串[]args){
/*
*对象在这里实例化,对吗?所以,函数#apply(整数)
*应定义并准备就绪。
*/
最终F3 F3=(a,b,c)->a*b
*c.长度();
最终整数a=3,b=13;
最后一个字符串c=“参见”;
预期的最终整数=a*b*c.length();
整数v1=f3。应用(a,b,c);
显示(“使用3调用”,预期为v1);
/*
*看来f3确实可以作为一个函数。。。
*/
整数v2=f3.应用(a).应用(b,c);
显示(“使用1然后2调用”,预期为v2);
/*
*从方法内部来看,没有问题。。。
*/
整数v3=workingReduce(f3,a)。应用(b,c);
显示(“在专用减速机内调用1”,预期为v3);
/*
*但当作为函数显式传递时,AbstractMethodError是
*从还原方法内部抛出。因此,似乎
*使用默认方法实现实例化对象
*不会发生在我认为会发生的地方。
*/
整数v4=brokenReduce(f3,a).apply(b,c);
显示(“调用通用减速机内部的1”,预期为v4);
}
专用静态无效显示(字符串标签、预期对象、实际对象){
System.out.println(标签+“:”
+(实际等于(预期)-“通过”:“失败”);
}
}

无论您使用什么编译器,这似乎都是一个bug。我只能用Eclipse编译器复制它。它可以很好地与

[~/workspace/Example/bin]$ javac -version
javac 1.8.0_05
[~/workspace/Example/bin]$ 

这里的错误似乎是编译器没有为调用方法添加
invokeinterface
,而是引用了抽象方法本身。或者它可能在没有
默认方法实现的情况下构建由lambda生成的实例,但这似乎不太可能,因为其他调用都可以工作。

您使用的是什么编译器?@SotiriosDelimanolis OracleJavac1.8.0\u05 for LinuxIt对我有效。您确定不是在IDE中编译吗?“我只能在日食中重现它。”索蒂里奥斯德里曼诺利斯·D'oh。是的,我正在使用Eclipse,但忘记了它不使用javac。这似乎是Eclipse编译器的问题。有趣的是,我已经在EclipseJava8编译器中发现了一些其他的bug,但我没有考虑检查这里是否存在这种情况。我确信我只是不理解本例中的语言语义。这份提交于6/2的Eclipse bug报告似乎描述了相同的问题: