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

时间:2008-08-24 12:03:28

标签: java generics syntax

我已经定义了一个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

4 个答案:

答案 0 :(得分:33)

当java编译器无法为静态方法自行推断参数类型时,您始终可以使用完全限定的方法名称传递它:Class。 &LT;输入&gt;方法();

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

答案 1 :(得分:22)

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

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

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

方法不能以与类型相同的方式进行泛化,因此具有动态类型泛型返回类型的方法的唯一选项 - phew是满口的:-) - 是将类型传递为参数。

关于Java泛型的真正优秀常见问题,see Angelika Langer's generics FAQ


<强>随访:

在此上下文中使用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 ] );
}

答案 2 :(得分:1)

自从我挖掘Java的那些部分以来已经有一段时间了,但是......

为什么你不能这样做可能是语言开发人员的设计选择。尽管如此,由于Java使用type erasure,泛型信息无论如何都会在编译时被删除,因此在您的示例中,无论您是否具有类型参数,它都会创建完全相同的字节代码。

答案 3 :(得分:0)

@pauldoo 是的,你是对的。这是java generics imho的弱点之一。

我对Cheekysoft的回应我想建议看一下Java人员自己如何做,比如T [] AbstractCollection#toArray(T [] a)。我认为Cheekysofts版本更优越,但Java版本具有熟悉的优势。

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


对Cheekysoft的跟进: 好吧,因为它是应该返回的某种类型的列表,相应的示例应该类似于:

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

但是,是的,传递类对象显然是更好的。我唯一的论点就是熟悉,在这个确切的例子中它不值得(事实上它很糟糕)。