已给予:
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.function.Function;
class Testcase
{
@FunctionalInterface
public interface MyBuilder1<R>
{
R apply(String message);
}
@FunctionalInterface
public interface MyBuilder2<R>
{
R apply(Object message);
}
public static void main(String[] args) throws Throwable
{
Class<?> clazz = IllegalArgumentException.class;
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle mh = lookup.findConstructor(clazz, MethodType.methodType(void.class, String.class));
MethodHandle myFunctionConstructor = LambdaMetafactory.metafactory(
lookup,
"apply",
MethodType.methodType(Function.class),
mh.type().erase(),
mh,
mh.type()
).getTarget();
MethodHandle myBuilderConstructor1 = LambdaMetafactory.metafactory(
lookup,
"apply",
MethodType.methodType(MyBuilder1.class),
mh.type().erase(),
mh,
mh.type()
).getTarget();
MethodHandle myBuilderConstructor2 = LambdaMetafactory.metafactory(
lookup,
"apply",
MethodType.methodType(MyBuilder2.class),
mh.type().erase(),
mh,
mh.type()
).getTarget();
@SuppressWarnings("unchecked")
Function<String, IllegalArgumentException> functionFactory =
(Function<String, IllegalArgumentException>) myFunctionConstructor.invokeExact();
@SuppressWarnings("unchecked")
MyBuilder1<IllegalArgumentException> myBuilder1Factory =
(MyBuilder1<IllegalArgumentException>) myBuilderConstructor1.invokeExact();
@SuppressWarnings("unchecked")
MyBuilder2<IllegalArgumentException> myBuilder2Factory =
(MyBuilder2<IllegalArgumentException>) myBuilderConstructor2.invokeExact();
IllegalArgumentException runFunction = functionFactory.apply("test");
// IllegalArgumentException runBuilder1 = myBuilder1Factory.apply("test");
IllegalArgumentException runBuilder2 = myBuilder2Factory.apply("test");
}
}
为什么runFunction
和runBuilder2
可以工作,而runBuilder1
抛出以下异常?
Java.lang.AbstractMethodError:Receiver类Testcase$$Lambda$233/0x0000000800d21d88没有定义或继承接口MyBuilder1的已解析方法‘Abstrative java.lang.Object Apply(java.lang.String)’的实现.
既然IllegalArgumentException
构造函数接受的是String
参数,而不是Object
参数,那么JVM不应该接受runBuilder1
并抱怨其他两个参数的类型吗?