带有泛型的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
}