泛型编程-2
上一篇 介绍了泛型最基本的用法,泛型类和泛型方法。
这篇将继续慢慢的解开泛型的面纱。
类型限定
有的时候方法或者类为了一些需求需要对泛型的的类型做出 一些限定。
假如:有一个类对象ArrayList中的的每一个元素实现了AutoCloseable,想要把他们全部关闭,可以如下写
public static <T extends AutoCloseable> void clossAll(ArrayList<T> elems)throws Exception{ for (T elem : elems) { elem.close(); } }
类型的变异和通配符
备用实体:
//人 public class Perion {} //雇员 public class Employee extends Perion{} //其他 public class Employee extends Perion{} //经理 public class Manager extends Employee {}
子类通配符
/** * 读取ArrayList<? extends Employee> 对象中的每一个元素 * @param staffs */ public static void printName(ArrayList<? extends Employee> staffs){ for (int i = 0; i < staffs.size();i++){ Employee employee = staffs.get(i); System.out.println(employee.getName()); } } /** * 修改操作 * 错误实例 不能编译通过 * add(capture<? extends genericity.gen4.Employee>)in ArrayList cannot be applied to (genericity.gen4.Employee) * @param staffs */ public static void add(ArrayList<? extends Employee> staffs){ Employee employee = new Employee("15", "测试"); staffs.add(employee); }
通过上面两个例子可以总结:可以将 <? extends Employee>转化成Employee但是不能将任何对象转化成Employee。可以限定返回值。可读。
父类型通配符
/** * 父类通配符 * @param employees */ public static void add2(ArrayList<? super Employee> employees){ Employee e = new Employee(); Manager m = new Manager(); employees.add(e); employees.add(m); //不能变译通过 // employees.add(new Other());
for (int i = 0;i < employees.size();i++){
//super 不能限制返回值 所以必须Object
Object obj = employees.get(i);
} } public static void main(String[] args) { ArrayList<? super Employee> es = new ArrayList<Employee>(); //不能变译通过 // List<? super Employee> es2 = new ArrayList<Manager>(); add2(es); }
可以看出super 可用于参数类型限定,不能用于返回类型限定。参数限定于Employee主干上。可写。
无限定通配符
/** * 无限定通配符 */ public static boolean hasNulls(ArrayList<?> elements){ for (Object element : elements) { if(element == null){ return true; } } return false; }
在某些情况下需要作非常通用的功能,可能会用到无限定通配符,如上检查ArrayList是否包含null值元素,由于ArrayList的类型是无关紧要的,所以使用ArrayList<?>完全可以。
带类型变量的通配符
/** * 带类型变量的通配符 *限制Predicate的参数和方法的类型参数完全匹配 ? super T * @param elements * @param filter * @param <T> */ public static <T> void printAll2(T[] elements ,Predicate<? super T> filter){ for (T e : elements) { if(filter.test(e)){ System.out.println(e.toString()); } } }
public interface Predicate<T> { /** * * @param arg * @return */ boolean test(T arg); }
可以看出统配的限定是一个类型的变量。