泛型编程-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);
}

可以看出统配的限定是一个类型的变量。

原文地址:https://www.cnblogs.com/java-gaolei/p/8284036.html