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

我已经定义了一个Java函数:

static  List createEmptyList() { return new ArrayList(); } 

调用它的一种方法是这样的:

 List myList = createEmptyList(); // Compiles 

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

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

我从编译器得到错误Illegal start of expression

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

 Object list = Collections. emptyList(); 

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

 static  List createEmptyList( Class type ) { return new ArrayList(); } @Test public void createStringList() { List stringList = createEmptyList( String.class ); } 

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

有关Javagenerics的真正优秀常见问题解答, 请参阅Angelika Langer的generics常见问题解答 。


跟进:

在此上下文中使用数组参数在Collection.toArray( T[] ) 。 在那里使用数组的唯一原因是因为使用相同的(预分配的)数组来包含结果(如果数组足够大以使它们全部适合)。 这节省了在运行时始终分配新arrays的过程。

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

 static  List createEmptyList( T[] array ) { return new ArrayList(); } @Test public void testThing() { List integerList = createEmptyList( new Integer[ 1 ] ); } 

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

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

@pauldoo是的,你是对的。 这是javagenericsimho的弱点之一。

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

编辑:添加链接。 重新编辑:在SO上发现了一个bug 🙂


关于Cheekysoft的后续行动:嗯,因为它是应该返回的某种类型的列表,相应的示例应该类似于:

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

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