我AbstractMethodError在调用一个方法时会收到一个,我认为该方法应该在目标实例中有一个默认实现.
我在三个参数中创建了一个功能接口,但也派生自java.util.function.Function并提供了一个默认实现Function#apply(..).然后我使用3参数lambda表达式创建我的接口实例.3参数方法都Function#apply(..)可以在创建的实例中正常工作.
当我将创建的实例传递给期望我的接口的方法时,我可以Function#apply(..)从方法中调用它并且它工作正常.
但是当我将实例传递给期望a的方法时Function,我会在AbstractMethodError尝试调用时收到Function#apply(..).
我似乎错过了对默认方法如何以及何时绑定到实例的理解.我做错了什么?
展示:
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"));
}
}
Run Code Online (Sandbox Code Playgroud)
这似乎是您正在使用的任何编译器中的错误.我只能用Eclipse编译器重现它.它工作得很好
[~/workspace/Example/bin]$ javac -version
javac 1.8.0_05
[~/workspace/Example/bin]$
Run Code Online (Sandbox Code Playgroud)
这里的错误似乎是编译器没有添加invokeinterface用于调用方法但是引用抽象方法本身.或者它可能在没有default方法实现的情况下构建由lambda生成的实例,但由于其他调用工作,这似乎不太可能.