JAVA泛型(二)类型通配符
类型通配符
为了表示各种泛型List的父类,可以使用类型通配符,类型通配符是一个问号(?)。
当直接使用List<?>这种形式时,即表明这个List集合可以是任何泛型List的父类。但还有一种情况,程序只希望它代表某一类泛型的父类。
被限制的类型通配符
//它表示泛型形参必须是Shape子类的List List<? extends Shape>
此处的问号<?>代表一个未知的类型,这个未知的类型必须是Shape的子类型(也可以是Shape本身),因此可以把Shape称为这个通配符的上限(upper bound)。
public class Canvas{ public void drawAll(List<? extends Shape> shapes){ for(Shape s : shapes){ s.drwa(this); } //下面代码引起编译错误 //shapes.add(0,new Rectangle()); } }
shapes.add()的第二个参数是? extends Shape,它表示Shape未知的子类,程序无法确定这个类型是什么,所以无法将任何对象添加到这种集合中(null例外)。
型变:指定通配符上限的集合,只能从集合中取出元素(取出的元素总是上限的类型),不能向集合中添加元素。
逆变:指定通配符下限的集合,只能向集合中添加元素(因为实际赋值的集合元素总是逆向声明的父类),不能取出元素(不确定取出的是哪个父类的对象)。
TreeSet(Comparable<? super E> c) public interface Comparator<T>{ int compare(T fst, T snd); }
通过这种带下限的通配符的语法,可以在创建TreeSet对象时灵活地选择合适的Comparator。若创建一个TreeSet<String>集合,那么这个Comparator可以是Comparator<String>,也可以是Comparator<Object>
import java.util.*; public class a{ public static void main(String[] args){ //Comparator的实际类型是TreeSet的元素类型的父类,满足要求 TreeSet<String> ts1 = new TreeSet<>(new Comparator<Object>(){ public int compare(Object fst, Object snd){ return hashCode() > snd.hashCode() ? 1 : hashCode() < snd.hashCode() ? -1 : 0; } }); ts1.add("hello"); ts1.add("wa"); //Comparator的实际类型是TreeSet元素的类型,满足要求 TreeSet<String> ts2 = new TreeSet<>(new Comparator<String>(){ public int compare(String first, String second){ return first.length() < second.length() ? -1 : first.length() > second.length() ? 1 : 0; } }); ts2.add("hello"); ts2.add("wa"); System.out.println(ts1); System.out.println(ts2); } }
设定泛型形参的上限
Java泛型不仅允许在使用通配符形参时设定上限,也可以在定义泛型形参时设定上限。
import java.util.*; public class a<T extends Number>{ T col; public static void main(String[] args){ a<Integer> a1 = new a<>(); a<Double> a2 = new a<>(); //编译异常,String不是Number的子类型 //a<String> a3 = new a<>(); } }
可以设置多个上限(至多有一个父类上限,可以有多个接口上限),表明该泛型形参是其父类的子类(或父类本身),并且实现多个上限接口
public class Apple<T extends Number & java.io.Serializable>{...}
浙公网安备 33010602011771号