泛型之通配符-上界下界

在泛型中,通配符 ? 是比较难理解的一部分,这里,我们介绍下 上界和下界。直接给代码,在代码中看注释比较清晰。
首先我们先准备一些类:

public class Pair<T> {

    private T first;
    private T second;

    public Pair(T first, T second) {
        this.first = first;
        this.second = second;
    }

    public T getFirst() {
        return first;
    }

    public T getSecond() {
        return second;
    }

    public void setFirst(T newValue) {
        first = newValue;
    }

    public void setSecond(T newValue) {
        second = newValue;
    }
}
class Employee {
    private String name;
    private double salary;

    public Employee(String n, double s) {
        name = n;
        salary = s;
    }

    public String getName() {
        return name;
    }

    public double getSalary() {
        return salary;
    }
}

class Manager extends Employee {
    public Manager(String n, double s) {
        super(n, s);
    }
}

现在进行测试:注释就是解释。

public class PairTest {
    // 这里要先知道,一个已知类型的容器,只能存放同种类型的数据(Object 容器除外)
    public static void main(String[] args) {
        Manager mgr1 = new Manager("Jack", 10000.99);
        Manager mgr2 = new Manager("Tom", 10001.01);

        Pair<Manager> managerPair = new Pair<Manager>(mgr1, mgr2);
        PairTest.printEmployeeBoddies(managerPair);

        // ? extends T 上界通配符 不能往里存,只能往外取
        // 用一个<? extends Employee> 接收一个 <Manager> ,因为 manager 是 Employee的子类
        Pair<? extends Employee> empPair = managerPair;
        // 这里,用 get 方法并没有出错
        PairTest.printEmployeeBoddies(empPair);
        // 但是用 set 方法就报错
//        empPair.setFirst(new Employee("zx",1234.0));
        // idea 提示 :
        // setFirst(capture<? extends Employee>) in Pair cannot be applied to(Employee)
        // 意思就是 ? extends Employee 类型 不能应用于  Employee 类型
        // 因为 ? 通配符 表示任意,? extends Employee 表示只要是 Employee 的子类,我都可以在初始化让他自来,
        // 并设置一个标识 CAP#1,而不是具体的字类类型,所以在初始化之后,
        // 我想给这个对象添加具体类型的子类时,因为子类型与标识 CAP#1 没法匹配,所以就不允许添加
        // 但是 我获取的时候,我知道CAP#1肯定是 Employee 本身或子类,所以我可以把一个子类赋值给其父类
        // 就是简单的 父类声明子类实例化

        /*
            empPair.setFirst(new Employee("as",1.2));  // 报错
            Pair<? extends Employee> 我们将 T 参数替换后,我们得到如下代码
            ? extends Employee first 擦拭 类型后 变成了 Employee first
            ? extends Employee getFirst() // 这里因为标识类型 肯定是 Employee 的子类或本身都可以赋值
            void setFirst(? extends Employee newVale)  // 这里 因为不能够确定 新值的类型,所以报错。
         */

        // ? super T 下界通配符
        Pair<? super Manager> pair = new Pair<Employee>(null, null);
        minMaxSal(new Manager[] {mgr1, mgr2}, pair);
//        Object pairFirst =  pair.getFirst();
//        Employee employee = (Employee) pairFirst;
//        System.out.println(employee.getName());
        // Employee employFirst =  pair.getFirst(); // 报错
        // idea 提示 :
        // Incompatible types. Required:Employee. Found: capture<? super Manager>
        // 意思是 我们需要返回的是Employee 类型,而捕获到的返回值却是 ? super Manager
        // 大家会产生一个问题,我们明明放的就是 Employee 类型,为什么获取出来的数据还得需要我们强转
        // 因为 super 只的是父类,只要是Manager 的父类都可以,所以在设置参数的情况下,不报错,因为 Employee 是Manager 的父类
        // 但是 我们在获取的情况就不一样的,获取出来时,编译器不知到是哪个父类,所以就统一采取了 Object 超类作为返回值,而在set 时,编译器可以半确定,肯定就是 Manager 本身或其父类并且父类顶端就是 Object, 所以用 set 的时, 只能够将数据保存到 Object 对象上。
        
        /*
         Pair<? super Manager> T 参数替换后,得到如下方法
         ? super Manager getFirst()  我们在获取的时候,不能够确定 ? 代表的是哪个类型 因为标识 CAP#1 不能够确定,但能确定的是 肯定是 Object 是所有类的基类

         void setFirst(? super Manager)  这里我们只能确定只要是 Manager 的父类就行。编译器虽然无法确定要set的类型,但可以肯定,
                                        一定是 Manager 的父类,并且是 Object 的子类或者这两者。
                                        所以就把 丢进来的对象赋值到了 Object 上。
         */

    }
    public static void printEmployeeBoddies(Pair<? extends Employee> pair) {
        System.out.println(pair.getFirst().getName() + ":" + pair.getSecond().getName());
    }
    public static void minMaxSal(Manager[] mgrs, Pair<? super Manager> pair) {
        if (mgrs == null || mgrs.length == 0) {
            return;
        }
        pair.setFirst(mgrs[0]);
        pair.setSecond(mgrs[0]);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值