【阶段三】
【目标:通配符和泛型的限定】
1,当使用了带有泛型的类时,需要传递具体类型实参时,无法明确要传递的实参,可以用?通配符表示。
2,如果要操作的对象的类型是在一个范围之内,比如只操作Person或者Person的子类型对象时。
这时可以使用泛型的限定,对要操作的类型进行限制,提高程序类型操作的安全性。
3,泛型限定体现:
? extends E :接受E类型或者E的子类型。上限。
? super E :接受E类型或者E的父类型。下限。
4,在api中的体现,要求看懂,并理解使用的原因。★★★★★
4.1 通配符的api体现:
Collection中的containsAll(Collection<?> c):因为该方法内部使用的是equals方法,
而equals(Object)方法是可以和任意对象进行比较,所以传递进来的集合元素是什么类型都可以,
无法确定具体的类型参数用?表示。
4.2 上下限api的体现。TreeSet集合的构造函数。
TreeSet(Collection<? extends E> c) :在给TreeSet集合初始化元素时,
传递进来的容器中的元素类型只要时TreeSet集合明确的类型或者子类型都可以。
TreeSet(Comparator<? super E> comparator) :在明确TreeSet比较器时,
只要是TreeSet集合元素类型的比较器,或者该元素类型的父类型都接收元素对象进行比较。
5,泛型限定的练习。★★★★★
获取Collection集合中的最大值。
5.1 先定义了一个方法中明确具体元素类型的getMax_1。
5.2 由于getMax_1无法获取其他类型元素的最大值。提高扩展性,操作所有对象。
就升级为了Object 。getMax_2
5.3 因为定义成Object,什么类型都可以接收,容易出现运行时的ClassCastException
所以使用泛型,对要操作的元素进行类型的限定。只有Comparable的子类才可以进行获取最值的操作。
public static <T extends Comparable<? super T>> T getMax_3(Collection<? extends T> c);
【学习结果】
1,看懂泛型限定在API中的体现,并会使用带有泛型限定的方法。
2,完成Collection集合最大值的获取,带有类型限定。★★★★★
public class GenericDemo5 {
//当使用泛型类或者接口时,传递的具体的类型不确定,可以通过通配符(?)表示。
public static void main(String[] args) {
Set<Student> set = new HashSet<Student>();
set.add(new Student("zhangsan",15));
set.add(new Student("lisi",12));
set.add(new Student("huangbo",5));
printList(set);
List<String> list2 = new ArrayList<String>();
list2.add("ansan");
list2.add("hjh");
list2.add("hbo");
printList(list2);
}
/**
* 打印集合中的元素
当使用泛型类或者接口时,传递的具体的类型不确定,可以通过通配符(?)表示。
* @param list2
*/
public static void printList(Collection<?> list2) {
for (Iterator<?> it = list2.iterator(); it.hasNext();) {
System.out.println(it.next());
}
}
}