通用方法vs通配符 - 编译错误 [英] Generic method vs wildcard - compilation error
问题描述
我有一个问题(简化):
public void method(List< List<>> list){...}
在使用以下函数调用时给了我一个编译错误:
method(new ArrayList< List< String>>()); //此行提供错误
阅读完类似的线程,我明白,如果我要重写方法签名,它将工作:
public void method(List< ;? extends List<>> list){...}
现在,我的问题是,为什么接下来的工作呢?
public< T> void method(List< List< T> list){...}
在处理多级通配符语法时会遇到混淆。让我们了解这些类型在那里的确切含义:
List< List<>>
是一个具体参数化类型。它是不同类型的 List< E>
的异构集合。由于 List<>
表示 List
的所有实例的族,所以您不能真正传递 ArrayList< List< String>>
到 List< List<>>
。因为,没有什么能阻止你在方法内部添加一个 List< Integer>
,并且在编译器允许它运行时会崩溃。
列表< ;? extends List<>>
是一个通配符参数化类型。它表示一系列不同类型的 List< E>
。基本上,它可能是 List< ArrayList< String>>< / code>,< code> List< LinkedList< Date>>
,等等。它可以是从 List<>
扩展的任何类型的列表。所以,将一个 ArrayList< List< String>>
传递给它是很安全的,因为你不会添加任何东西,但是 null
到列表中。 ArrayList< List< String>>
,类型 T
将被推断为Ť
。泛型方法处理用它声明的类型。所以,这里只有一个类型 T
。您从 List< List< T>>< / code>列出的所有列表肯定会是
List< T>
for任何类型 T
。因此,这是 List
类型的同质集合。在该方法中,不能向 List< List< T>>< / code>添加任意的
List< E> ,因为编译器不知道该类型
E
是否与 T
兼容或不兼容。所以,这是安全的调用。
相关:
I had a issue where (to simplify):
public void method(List<List<?>> list){...}
gave me a compilation error when called with:
method(new ArrayList<List<String>>()); // This line gives the error
After reading a similar thread, I understood that it would work if I were to rewrite the method signature as:
public void method(List<? extends List<?>> list){...}
Now, my question is, why does the following work then?
public <T> void method(List<List<T>> list){...}
Confusions do come when you deal with multi-level wildcard syntax. Let's understand what those types exactly mean in there:
List<List<?>>
is a concrete parameterized type. It is a heterogenous collection of different types ofList<E>
. SinceList<?>
represent a family of all the instantiation ofList
, you can't really pass anArrayList<List<String>>
toList<List<?>>
. Because, nothing stops you from adding aList<Integer>
to it inside the method, and that will crash at runtime, had compiler allowed it.List<? extends List<?>>
is a wildcard parameterized type. It represents a family of different types ofList<E>
. Basically, it might be aList<ArrayList<String>>
,List<LinkedList<Date>>
, so on. It can be a list of any type that extend from aList<?>
. So, it will be safe to pass aArrayList<List<String>>
to it, the reason being, you won't be allowed to add anything, butnull
to the list. Adding anything to the list will be a compile time error.As for
List<List<T>>
, it is again a concrete parameterized type. And since you're dealing with a generic method now, the type parameter will be inferred to be the type that is passed for it. So, for anArrayList<List<String>>
, typeT
will be inferred asT
. A generic method deals with the types that are declared with it. So, there is only a single typeT
here. All the lists you get out ofList<List<T>>
will certainly be aList<T>
for any typeT
. So, it's a homogenous collection of that type ofList
. Inside the method, you can not add any arbitraryList<E>
to theList<List<T>>
, because the compiler doesn't know whether that typeE
is compatible withT
or not. So, it is safe invocation.
Related:
- Multiple wildcards on a generic methods makes Java compiler (and me!) very confused
- Java HashMap nested generics with wildcards
- What are multi-level wild cards? Confusion in syntax
- When to use generic methods and when to use wild-card?
这篇关于通用方法vs通配符 - 编译错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!