泛型的继承和通配符

泛型的继承和通配符

一:泛型的继承和通配符

(1)泛型不具备继承性,但是数据具备继承性

泛型不具备继承性:

public class Test7 {
    public static void main(String[] args) {
        // 泛型不具备继承性,但是数据具备继承性
        // 创建集合的对象
        ArrayList<Ye> list1 = new ArrayList<>();
        ArrayList<Fu> list2 = new ArrayList<>();
        ArrayList<Zi> list3 = new ArrayList<>();
        // 调用method方法
        method(list1);
        method(list2); // 编译报错
        method(list3); // 编译报错
    }
    // 此时,泛型里面写的是什么类型,那么只能传递什么类型的数据。
    // 传递list2或者是list3都不行,只有你传list1才是可以的。因为list1集合里面装的是Ye,跟这里的形参是完全一致的。
    // 这个就是泛型不具备继承性
    public static void method(ArrayList<Ye> list) {
    }
}

class Ye{}
class Fu extends Ye{}
class Zi extends Fu{}

数据具备继承性:

public class Test7 {
    public static void main(String[] args) {
        // 泛型不具备继承性,但是数据具备继承性
        // 创建集合的对象
        ArrayList<Ye> list1 = new ArrayList<>();
        ArrayList<Fu> list2 = new ArrayList<>();
        ArrayList<Zi> list3 = new ArrayList<>();

        // 但是数据具备继承性
        // 我现在可以往集合里面添加,可以添加Ye的对象,还可以添加Fu的对象,还可以添加Zi的对象
        // 这个就叫做数据具备继承性
        list1.add(new Ye());
        list1.add(new Fu());
        list1.add(new Zi());
    }
    // 此时,泛型里面写的是什么类型,那么只能传递什么类型的数据。
    // 传递list2或者是list3都不行,只有你传list1才是可以的。因为list1集合里面装的是Ye,跟这里的形参是完全一致的。
    // 这个就是泛型不具备继承性
    public static void method(ArrayList<Ye> list) {
    }
}

class Ye{}
class Fu extends Ye{}
class Zi extends Fu{}

需求:定义一个方法,形参是一个集合,但是集合中的数据类型不确定

public class Test8 {
    public static void main(String[] args) {
        // 需求:定义一个方法,形参是一个集合,但是集合中的数据类型不确定
        // 创建集合的对象
        ArrayList<Ye> list1 = new ArrayList<>();
        ArrayList<Fu> list2 = new ArrayList<>();
        ArrayList<Zi> list3 = new ArrayList<>();
        ArrayList<Student> list4 = new ArrayList<>();
        method(list1);
        method(list2);
        method(list3);
        method(list4);
    }
    // 既然这里的类型不确定,是不是可以用刚刚学的泛型方法去搞定?完全可以
    // 这里定义一个泛型E,ArrayList里面就可以用上这个E了
    // 此时创建三个集合的对象,再去调用method方法,可以把list1、list2、list3传递过去,传递过去都没问题
    // 但是此时会有一个弊端:
    // 利用泛型方法会有一个小弊端,此时它可以接收任意的数据类型,包括我们定义的Ye、Fu、Zi,甚至是你定义一个其他的例如Student类,
    // 不在前面的继承结构当中,比如说一个Student,都是可以传递过去的。method(list4);没有报错,因为这里的method方法可以接受任意的数据类型
    // 因为这里的E就是不确定的类型,随便传递一个过来都是可以的
    // 但是在有的时候我们不希望是这样的,我们希望:本方法虽然不确定类型,但是以后我希望只能传递Ye Fu Zi,不希望能传递Student2
    // 那该怎么办?
    // 难不成直接在泛型里面写个Ye?public static void method(ArrayList<Ye> list) {},不可以!
    // 因为刚刚才说过,泛型是不具备继承性的,所以和刚刚一样:传递Ye,和他一样是可以的,但是传递Fu和Zi的时候就不行了。
    // 这个时候怎么解决?
    // 此时我们就可以使用泛型的通配符,在java当中泛型的通配符就是一个 ? ,他也表示不确定的类型,也就是一切类型
    // 但是他可以进行类型的限定,它的限定方式有两种:
    // ? extends E: 表示可以传递E或者E所有的子类类型
    // ? super E: 表示可以传递E或者E所有的父类类型
    // 按照这样(public static void method(ArrayList<? extends Ye> list) {})写了过后:
    // methods(list4)就会报错了,因为list4和集成结构没有关系
    // 如果是(public static void method(ArrayList<? super Zi> list) {}),就表示现在传递的类型必须是Zi或者Zi的父类类型

    // 应用场景:
    //      1.如果我们在定义类、方法、接口的时候,如果类型不确定,就可以定义泛型类、泛型方法、泛型接口
    //      2.如果类型不确定,但是能知道以后只能传递某个继承体系中的,就可以用泛型的通配符
    // 泛型的通配符:
    //      关键点:可以限定类型的范围
    //		而且使用这个泛型通配符?的话,前面可以不用定义这个?哦
    public static void method(ArrayList<? super Zi> list) {}
}
class Ye {}
class Fu extends Ye {}
class Zi extends Fu {}
class Student {}

泛型总结:

(1)什么是泛型?

JDK5引入的特性,可以在编译阶段约束操作的数据类型,并进行检查

(2)泛型的好处?

1.统一数据类型

2.把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为在编译阶段类型就能确定下来

(3)泛型的细节?

1.泛型中不能写基本数据类型

2.指定泛型的具体类型后,传递数据时,可以传入该类型和他的子类类型

3.如果不写泛型,类型默认是Object

(4)哪里定义泛型?

1.泛型类:在类名后面定义泛型,创建该类对象的时候,确定类型

2.泛型方法:在修饰符后面定义方法,调用该方法的时候,确定类型

3.泛型接口:在接口名后面定义泛型,实现类确定类型,实现类延续泛型

(5)泛型的继承和通配符

1.泛型不具备继承性,但是数据具备继承性

2.泛型的通配符有:?

​ ? extends E:E和E的子类

​ ? super E:E和E的父类

(6)使用场景

1.定义类、方法、接口的时候,如果类型不确定,就可以定义泛型

2.如果类型不确定,但是能知道是哪个继承体系中的,可以使用泛型的通配符

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值