通用方法vs通配符 - 编译错误 [英] Generic method vs wildcard - compilation error

查看:69
本文介绍了通用方法vs通配符 - 编译错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题(简化):

  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 到列表中。

  • $ c>,它又是一个具体的参数化类型。因为你现在正在处理一个通用的方法,所以类型参数将被推断为为其传递的类型。因此,对于 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 of List<E>. Since List<?> represent a family of all the instantiation of List, you can't really pass an ArrayList<List<String>> to List<List<?>>. Because, nothing stops you from adding a List<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 of List<E>. Basically, it might be a List<ArrayList<String>>, List<LinkedList<Date>>, so on. It can be a list of any type that extend from a List<?>. So, it will be safe to pass a ArrayList<List<String>> to it, the reason being, you won't be allowed to add anything, but null 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 an ArrayList<List<String>>, type T will be inferred as T. A generic method deals with the types that are declared with it. So, there is only a single type T here. All the lists you get out of List<List<T>> will certainly be a List<T> for any type T. So, it's a homogenous collection of that type of List. Inside the method, you can not add any arbitrary List<E> to the List<List<T>>, because the compiler doesn't know whether that type E is compatible with T or not. So, it is safe invocation.


Related:

这篇关于通用方法vs通配符 - 编译错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆