带有泛型的Java lambda类型
运行以下代码时:带有泛型的Java lambda类型,java,generics,lambda,java-8,Java,Generics,Lambda,Java 8,运行以下代码时: import java.lang.reflect.Type; import java.util.Arrays; import java.util.List; class A { private static final List<Adapter<? extends Number>> adapters = Arrays.asList( Integer::valueOf, s -> Long.v
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
class A {
private static final List<Adapter<? extends Number>> adapters = Arrays.asList(
Integer::valueOf,
s -> Long.valueOf(s),
(Adapter<Float>) s -> Float.valueOf(s),
new Adapter<Double>() {
@Override
public Double adapt(String s) {
return Double.valueOf(s);
}
}
);
private interface Adapter<T> {
T adapt(String s);
default Type type() {
try {
return getClass().getMethod("adapt", String.class).getReturnType();
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
}
}
}
public static void main(String[] args) {
for (Adapter<?> adapter : adapters) {
System.out.printf("Got adapter for type %s%n",
adapter.type().getTypeName());
}
}
}
我很好奇为什么只有最后一个适配器被识别为Double,其余的是Object(而不是Integer、Long和Float)。至少,我希望他们是数字
new Adapter<Double>() {
@Override
public Double adapt(String s) {
return Double.valueOf(s);
}
}
正如您所看到的,A$1.adapt
类通过编译器推断出了Double
类型
对于
Lambda表达式
,编译器只需将其作为invokedynamic#2,0//invokedynamic#0:adapt:()LA$Adapter代码>,因此是由类型擦除引起的,这将是该类型的对象。有趣的问题。。。可能与编译器捕获泛型类型的方式有关。可以在JLS中查找。希望这里有人知道从哪里引用。
new Adapter<Double>() {
@Override
public Double adapt(String s) {
return Double.valueOf(s);
}
}
Compiled from "A.java"
final class A$1 implements A$Adapter<java.lang.Double> {
A$1();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public java.lang.Double adapt(java.lang.String);
Code:
0: aload_1
1: invokestatic #2 // Method java/lang/Double.valueOf:(Ljava/lang/String;)Ljava/lang/Double;
4: areturn
public java.lang.Object adapt(java.lang.String);
Code:
0: aload_0
1: aload_1
2: invokevirtual #3 // Method adapt:(Ljava/lang/String;)Ljava/lang/Double;
5: areturn
}