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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24991/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 07:16:30  来源:igfitidea点击:

Why can't I explicitly pass the type argument to a generic Java method?

javagenericssyntax

提问by pauldoo

I have defined a Java function:

我定义了一个 Java 函数:

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

One way to call it is like so:

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

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

Why can't I call it by explicitly passing the generic type argument? :

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

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

I get the error Illegal start of expressionfrom the compiler.

Illegal start of expression从编译器那里得到错误。

采纳答案by Henrik Gustafsson

When the java compiler cannot infer the parameter type by itself for a static method, you can always pass it using the full qualified method name: Class . < Type > method();

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

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

回答by Cheekysoft

You can, if you pass in the type as a method parameter.

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

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

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

Methods cannot be genericised in the same way that a type can, so the only option for a method with a dynamically-typed generic return type -- phew that's a mouthful :-) -- is to pass in the type as an argument.

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

For a truly excellent FAQ on Java generics, see Angelika Langer's generics FAQ.

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

.
.

.
.

Follow-up:

跟进:

It wouldn't make sense in this context to use the array argument as in Collection.toArray( T[] ). The only reason an array is used there is because the same (pre-allocated) array is used to contain the results (if the array is large enough to fit them all in). This saves on allocating a new array at run-time all the time.

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

However, for the purposes of education, if you did want to use the array typing, the syntax is very similar:

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

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

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

回答by Henrik Gustafsson

@pauldoo Yes, you are quite right. It is one of the weaknesses with the java generics imho.

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

I response to Cheekysoft I'd like to propose to also look at how it is done by the Java people themselves, such as T[] AbstractCollection#toArray(T[] a). I think Cheekysofts version is superior, but the Java one has the advantage of familiarity.

我回应 Cheekysoft 我想提议也看看 Java 人自己是如何完成的,例如 T[] AbstractCollection#toArray(T[] a)。我认为 Cheekysofts 版本更胜一筹,但 Java 版本具有熟悉的优势。

Edit: Added link. Re-edit: Found a bug on SO :)

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



Follow-up on Cheekysoft: Well, as it is a list of some type that should be returned the corresponding example should look something like:

Cheekysoft 的后续行动:嗯,因为它是应该返回的某种类型的列表,所以相应的示例应该如下所示:

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

But yes, passing the class object is clearly the better one. My only argument is that of familiarity, and in this exact instance it isn't worth much (in fact it is bad).

但是,是的,传递类对象显然是更好的方法。我唯一的论点是熟悉度,在这个确切的例子中它没有多大价值(实际上它很糟糕)。