您的位置:首页 > 编程语言 > Java开发

JAVA泛型与通配符详解

2017-11-28 09:35 267 查看
问:什么是 Java 泛型中的限定通配符和非限定通配符?有什么区别?

答:限定通配符对类型进行限制,泛型中有两种限定通配符,一种是 <? extends T> 来保证泛型类型必须是
T 的子类来设定泛型类型的上边界,另一种是 <? super T> 来保证泛型类型必须是 T 的父类来设定类型的下边界,泛型类型必须用限定内的类型来进行初始化,否则会导致编译错误。非限定通配符 <?> 表示可以用任意泛型类型来替代,可以在某种意义上来说是泛型向上转型的语法格式,因为 List<String> 与 List<Object> 不存在继承关系。

问:简单说说 List<Object> 与 List 原始类型之间的区别?

答:主要区别有两点。

原始类型和带泛型参数类型 <Object> 之间的主要区别是在编译时编译器不会对原始类型进行类型安全检查,却会对带参数的类型进行检查,通过使用 Object 作为类型可以告知编译器该方法可以接受任何类型的对象(比如 String 或 Integer)。

我们可以把任何带参数的类型传递给原始类型 List,但却不能把 List<String> 传递给接受 List<Object> 的方法,因为会产生编译错误。

问:简单说说 List<Object> 与 List<?> 类型之间的区别?

答:这道题跟上一道题看起来很像,实质上却完全不同。List<?> 是一个未知类型的 List,而
List<Object> 其实是任意类型的 List,我们可以把 List<String>、List<Integer> 赋值给 List<?>,却不能把 List<String> 赋值给 List<Object>。譬如:

List<?> listOfAnyType;

List<Object> listOfObject = new ArrayList<Object>();

List<String> listOfString = new ArrayList<String>();

List<Integer> listOfInteger = new ArrayList<Integer>();

listOfAnyType = listOfString; //legal

listOfAnyType = listOfInteger; //legal

listOfObjectType = (List<Object>) listOfString; //compiler error


所以通配符形式都可以用类型参数的形式来替代,通配符能做的用类型参数都能做。 通配符形式可以减少类型参数,形式上往往更为简单,可读性也更好,所以能用通配符的就用通配符。 如果类型参数之间有依赖关系或者返回值依赖类型参数或者需要写操作则只能用类型参数。

问:List<? extends T>和List <? super T>之间有什么区别?

答:有时面试官会用这个问题来评估你对泛型的理解,而不是直接问你什么是限定通配符和非限定通配符,这两个
List 的声明都是限定通配符的例子,List<? extends T> 可以接受任何继承自 T 的类型的 List,而 List<? super T> 可以接受任何 T 的父类构成的 List。例如 List<? extends Number> 可以接受 List<Integer> 或 List<Float>。Java 容器类的实现中有很多这种用法,比如  Collections 中就有如下一些方法:

public static <T extends Comparable<? super T>> void sort(List<T> list)

public static <T> void sort(List<T> list, Comparator<? super T> c)

public static <T> void copy(List<? super T> dest, List<? extends T> src)

public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp)


问:说说 <T extends E> 和 <? extends E> 有什么区别?

答:它们用的地方不一样,<T
extends E> 用于定义类型参数,声明了一个类型参数 T,可放在泛型类定义中类名后面、接口后面、泛型方法返回值前面。 <? extends E> 用于实例化类型参数,用于实例化泛型变量中的类型参数,只是这个具体类型是未知的,只知道它是 E 或 E 的某个子类型。虽然它们不一样,但两种写法经常可以达到相同的目的,譬如:

public void addAll(Bean<? extends E> c)

public <T extends E> void addAll(Bean<T> c)


问:说说 List<String> 与 List<Object> 的关系和区别?

答:这两个东西没有关系只有区别。

因为也许很多人认为 String 是 Object 的子类,所以 List<String> 应当可以用在需要 List<Object> 的地方,但是事实并非如此,泛型类型之间不具备泛型参数类型的继承关系,所以 List<String> 和 List<Object> 没有关系,无法转换。

老铁们,别嫌短,长了你肯定不会看完的,所以这就是码农每日一题的宗旨(其他历史文章请查看公众号历史记录)~

看完分享一波嘛,和你的小伙伴一起讨论才更加有意思,右上角分享
666~

The most important thing is to enjoy life - to be happy.

最重要的是享受生活 - 要快乐。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息