← 返回首页
JavaSE系列教程(七十七)
发表时间:2020-02-23 14:34:45
讲解泛型接口和泛型上下界

1.什么是泛型接口

泛型接口的定义: 在接口名后面加上泛型类型参数T,这样就定义了一个泛型接口。 例如:

public interface MyInterface<T>{
}

实例:

public interface IDao<T> {

    void print(T obj);
}
public class IDaoImpl implements IDao<String> {

    @Override
    public void print(String obj) {
        System.out.println("obj type is: " + obj.getClass().getName()+",value is:"+obj);
    }

    public static void main(String[] args) {
        new IDaoImpl().print("hello,world!");
    }
}

运行结果:
obj type is: java.lang.String,value is:hello,world!

2.泛型的上下界

上界用extends关键字声明,表示参数化的类型可能是所指定的类型,或者是此类型的子类。 下界用super进行声明,表示参数化的类型可能是所指定的类型,或者是此类型的父类型,直至Object。

形如 List<? extends B>,具体哪一种不能确定,既可以是 B,也可以是 C。在尝试执行 add() 方法时,List中的类型不能确定是具体哪一种,所以会编译报错。在执行 get() 方法时,不管是 B 还是 C,都可以以 A 类对象来接收。所以 List<? extends B> 不能添加元素,具有只读属性,只能获取。

形如 List<? super B>,具体哪一种不能确定,既可以是 B,也可以是 A,直至 Object类。在尝试执行 add() 方法时,虽然 List 的具体类型不能确定,但是根据多态, B 类及其子类的对象肯定都可以被赋值给 B 的对象,所以只能添加 B 类及其子类的对象。在尝试执行 get() 方法时,List 中的类型是 B 类或者其父类的具体一种,向上直至 Object 类,所以只能将获取的元素赋值给 Object 对象。

实例:

class Animal {
    protected String alias;

    public Animal(String alias) {
        this.alias = alias;
    }
}

class Cat extends Animal {
    public Cat(String alias) {
        super(alias);
    }

    @Override
    public String toString() {
        return "Cat{" +
                "alias='" + alias + '\'' +
                '}';
    }
}

class Dog extends Animal {
    public Dog(String alias) {
        super(alias);
    }

    @Override
    public String toString() {
        return "Dog{" +
                "alias='" + alias + '\'' +
                '}';
    }
}

public class GenerateDemo {

    public static void main(String[] args) {

        List<Animal> animalList = new ArrayList<Animal>();

        List<Dog> dogs = new ArrayList<Dog>();
        dogs.add(new Dog("旺财"));
        List<Cat> cats = new ArrayList<Cat>();
        cats.add(new Cat("Tom"));
        //定义下界,只能接收Dog或者是Dog的父类的集合
        List<? super Dog> list1 = dogs;
        List<? super Dog> list2 = animalList;
        list2.add(new Dog("黑贝")); //下界只能添加Dog或者Dog的子类对象。
        //List<? super Dog> list3 = cats; //错误。

        for(Object obj: list2){ //下界遍历只能使用Object.
            System.out.println(obj);
        }

        //定义上界,只能接收Animal或者是Animal的子类
        List<? extends Animal> animals1 = animalList;
        List<? extends Animal> animals2 = dogs;
        List<? extends Animal> animals3 = cats;

        //注意:上界的集合是只读的,不能添加。
        //animals2.add(new Dog("黑贝")); //注意上界集合不能添加
        for (Animal a : animals2) {
            System.out.println(a);
        }
    }
}

运行结果:
Dog{alias='黑贝'}
Dog{alias='旺财'}

小结:

1).? extends X 指明类型的上界限定为 X,表示传入方法的类型参数必须是其本身或子类。上界只能读取,不能添加。主要考虑到用于安全地访问数据,可以访问X及其子类型,并且不能写入非null的数据。

2).? super X ,指明类型的下界限定为 X,表示传入方法的类型参数必须是其本身或其父类。下界只能添加,不能读取。主要考虑用于安全地写入数据,可以写入X及其子类型。