构造函数中的泛型推理

2022-09-04 20:41:45

如果我有一个类:Foo

public class Foo<T> {
    public Foo(T t) {
        //do something
    }

    public static <E> void bar(E e) {
         //do something
    }
}

为什么推断这是一个字符串(因此不会引发编译器警告),而不是推断它是一个字符串?Foo.bar("String");Enew Foo("String");T


答案 1

因为构造函数可以被认为是一个特殊的实例方法,所以它不是类型化的 - 它从类名(带有类型参数)获取其类型,例如。即构造函数未定义为:Foo<String>

public <T> Foo(T t) ...

也不可能。这样做会隐藏类的泛型类型(并且你会收到警告)

但是,静态方法是类型化的。仅供参考,一旦推断出类型,无泛型参数调用就相当于:

Foo.<String>bar("String");

答案 2

当Java实现泛型时,决定没有类型参数的实例化泛型类将始终返回原始类型。这与缺少类型参数的泛型方法不同,编译器会尝试推断其类型。从 Java 教程中:

通常,Java 编译器可以推断泛型方法调用的类型参数。因此,在大多数情况下,您不必指定它们。

但是当讨论转向构造函数时:

请注意,若要在泛型类实例化期间利用自动类型推断,必须指定菱形。在下面的示例中,编译器生成一个未经检查的转换警告,因为 HashMap() 构造函数引用的是原始类型,而不是类型:HashMapMap<String, List<String>>

Map<String, List<String>> myMap = new HashMap(); // unchecked conversion warning

来源:http://download.oracle.com/javase/tutorial/java/generics/gentypeinference.html

这在Java 7中保持不变,但是他们试图通过支持菱形语法来减少重复。例如。请参阅同一篇文章的此部分Foo<String> foo = new Foo<>("String")


推荐