简体   繁体   English

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

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

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 expression from the compiler.我从编译器收到错误Illegal start of expression

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

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

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

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[] ) . 在此上下文中使用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. 这节省了在运行时始终分配新阵列的过程。

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 ] );
}

It was quite some time since I dug into those parts of Java, but... 自从我挖掘Java的那些部分以来已经有一段时间了,但......

Why you can't do it was probably a design choice by the language developers. 为什么你不能这样做可能是语言开发人员的设计选择。 Still, due to the type erasure employed by Java, the generics information gets dropped at compile time anyway, so in your example it would create exactly the same byte code whether you had the type parameter or not. 尽管如此,由于Java使用的类型擦除 ,泛型信息无论如何都会在编译时被删除,因此在您的示例中,无论您是否具有类型参数,它都将创建完全相同的字节代码。

@pauldoo Yes, you are quite right. @pauldoo是的,你是对的。 It is one of the weaknesses with the java generics imho. 这是java泛型imho的弱点之一。

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). 我对Cheekysoft的回应我想建议看一下Java人员自己如何做,比如T [] AbstractCollection#toArray (T [] a)。 I think Cheekysofts version is superior, but the Java one has the advantage of familiarity. 我认为Cheekysofts版本更优越,但Java版本具有熟悉的优势。

Edit: Added link. 编辑:添加链接。 Re-edit: Found a bug on SO :) 重新编辑:在SO上发现了一个bug :)


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). 我唯一的论点就是熟悉,而在这个确切的例子中它并不值得(事实上它很糟糕)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 爪哇。 如果在方法定义中参数是接口类型,为什么我可以传递对象参数? - Java. Why can i pass an object argument, if in the method definition the arguments are the type of an interface? 一个带有泛型参数的java方法 - 为什么我不能传递一个带有泛型参数的对象,该参数是方法参数的子类? - A java method that has a generic parameter- why can't I pass an object with a generic parameter that is a subclass of the method arguments? Java通用方法类型参数 - Java generic method type argument Java方法如何接受扩展通用类型的参数 - How can a java method take an argument that extends a generic type 为什么我不能从方法中显式返回 void? - Why can't I explicitly return void from a method? 为什么不能扩展接口“泛型方法”并将其类型缩小到继承的接口“类通用”? - Why can't I extend an interface “generic method” and narrow its type to my inherited interface “class generic”? Java泛型:为什么编译器无法在方法中将T类型解析为继承类型? - Java Generic: Why compiler can not resolve type T to inherited type in method? 如何调用以泛型T []作为参数的方法? - How do I call a method with a generic type T[] as an argument? 给定泛型类型参数,如何调用相应的方法? - How can I call the corresponding method given the generic type argument? 为什么我不能将参数传递给toString()方法,为什么它给出null? - Why can't I pass an argument into a toString() method and why does it give a null?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM