当实例作为其超级接口传递时,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报告似乎描述了相同的问题: