泛型-类型通配符的下限
Posted shadow-shine
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了泛型-类型通配符的下限相关的知识,希望对你有一定的参考价值。
除了可以指定通配符的上限之外,Java也允许指定通配符的下限,通配符的下限用<? super 类型>的方式指定,通配符下限的作用于通配符上限的作用恰好相反.
指定通配符的下限就是为了支持类型型变.比如Foo是Bar的子类,当程序需要一个A<? super Bar>变量时,程序可以将A<Foo>,A<Object>赋值给A<? super Bar>类型的变量,这种方法被称为逆变.
对于逆变的泛型集合来说,编译器只知道集合元素是下限的父类型,但具体是哪一种父类型则不确定.因此,这种逆变的泛型集合只能向其中添加元素(因为实际赋值的集合元素总是逆变声明的父类),从集合中去元素只能被当成Object类型处理(编译器无法确定取出的到底是哪个父类的对象).
假设自己实现了一个工具方法:实现将src集合中的元素复制到dest集合的功能,因此dest集合可以保存src集合中的所有元素,所以dest集合元素的类型应该是src集合元素类型的父类.
对于上面的copy()方法,可以这样理解两个集合参数之间的依赖关系:不管src集合元素的类型是什么,只要dest的集合元素的类型与前者相同或者是前者的父类即可.
package com.j1803.Type_wildcards;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class MyUtils {
//下面的dest集合元素的类型必须与src集合元素的类型相同,或者是其父类
public static <E> E copy(Collection<? super E>dest,Collection<E>src){
E last=null;
for(E ele:src){
last=ele;
//逆变的泛型集合添加元素是安全的
dest.add(last);
}
return last;
}
public static void main(String[] args) {
List<Shape>list1=new ArrayList<>();
List<Circle>list2=new ArrayList<>();
list2.add(new Circle());
list2.add(new Circle());
Circle circle=MyUtils.copy(list1,list2);
System.out.println(circle);
}
}
answer:
[email protected]
上面的方法用到了泛型方法的语法,就是在方法修饰符和返回值类型之间用<>定义泛型形参.
========================================================================================================================
设定泛型形参的上限
Java泛型不仅允许在使用通配符形参时设定上限,而且可以在定义泛型形参时设定上限,用于表示传给该泛型的形参的实际类型要么是该上限类型,要么就是该上限类型的子类.
package com.j1803.Type_wildcards;
public class AppleDemo <E extends Number>{
private E info;
public AppleDemo(E info) {
this.info = info;
}
public E getInfo() {
return info;
}
public static void main(String[] args) {
AppleDemo<Integer> ai=new AppleDemo<>(23);
//AppleDemo<Integer> ai1=new AppleDemo<>(45.23);//编译错误
AppleDemo<Double> di=new AppleDemo<>(23.23);
//AppleDemo<Double> di1=new AppleDemo<>(45);//编译出错
//AppleDemo<String> s1=new AppleDemo<String>();//编译出错
System.out.println(ai.getInfo());
System.out.println(di.getInfo());
}
}
程序定义了一个AppleDemo泛型类,该AppleDemo类的泛型形参的上限是Number类,这表明使用AppleDemo类时为E形参传入实际类型参数的只能时Number或者Number的子类.
还有一种更极端的情况下,程序需要为为泛型形参设定多个上限(至多有一个父类上限,可以有多个接口上限),表明该泛型形参必须是其父类的子类(是父类本身也行),并且有多个上限接口.如下代码
//表明T类型必须是Number类或其子类,并必须实现java.io.serializable接口
public class AppleDemo<T extends Number & java.io.Seriable>{
......
}
以上是关于泛型-类型通配符的下限的主要内容,如果未能解决你的问题,请参考以下文章