为什么我不能显式地将类型参数传递给泛型 Java 方法?

问题描述 投票:0回答:4

我定义了一个Java函数:

static <T> List<T> createEmptyList() {
    return new ArrayList<T>();
}

一种调用方式如下:

List<Integer> myList = createEmptyList(); // Compiles

为什么我不能通过显式传递泛型类型参数来调用它? :

Object myObject = createEmtpyList<Integer>(); // Doesn't compile. Why?

我从编译器中收到错误

Illegal start of expression

java generics syntax
4个回答
49
投票

当 java 编译器无法自行推断静态方法的参数类型时,您始终可以使用完整限定方法名称传递它: Class 。 < Type > 方法();

Object list = Collections.<String> emptyList();

26
投票

如果您将类型作为方法参数传递,则可以。

static <T> List<T> createEmptyList( Class<T> type ) {
  return new ArrayList<T>();
}

@Test
public void createStringList() {
  List<String> stringList = createEmptyList( String.class );
}

方法不能像类型一样进行泛型化,因此对于具有动态类型泛型返回类型的方法来说,唯一的选择——唷,这真是拗口:-)——是将类型作为参数传递。

有关 Java 泛型的真正优秀的常见问题解答,请参阅 Angelika Langer 的泛型常见问题解答

.

后续:

在这种情况下,像

Collection.toArray( T[] )
那样使用数组参数是没有意义的。在那里使用数组的唯一原因是因为使用相同的(预分配的)数组来包含结果(如果数组足够大以容纳所有结果)。这可以节省在运行时分配新数组的时间。

但是,出于教育目的,如果您确实想使用数组类型,则语法非常相似:

static <T> List<T> createEmptyList( T[] array ) {
  return new ArrayList<T>();
}

@Test
public void testThing() {
  List<Integer> integerList = createEmptyList( new Integer[ 1 ] );
}

0
投票

@pauldoo 是的,你说得很对。恕我直言,这是 java 泛型的弱点之一。

我对 Cheekysoft 的回应我想建议也看看 Java 人员自己是如何完成的,例如 T[] AbstractCollection#toArray(T[] a)。我认为 Cheekysofts 版本更好,但 Java 版本的优点是熟悉。

编辑:添加链接。 重新编辑:发现了一个错误:)


Cheekysoft 的后续报道: 好吧,因为它是应该返回的某种类型的列表,所以相应的示例应该类似于:

static <T> List<T> createEmptyList( List<T> a ) {
  return new ArrayList<T>();
}

但是,是的,传递类对象显然是更好的选择。我唯一的论点是熟悉度,在这种情况下它没有多大价值(事实上它很糟糕)。


0
投票

如果是在同一个班级,可以按如下方式进行:

List<String> list = this.<String>createEmptyList();

编译器当然会告诉你它是“多余的”。

© www.soinside.com 2019 - 2024. All rights reserved.