java泛型学习

泛型

## 泛型理解及作用

​ 我们知道,java里面数组可以存储数据,并且只能存储同一种类型的数据,但是他有一个弊端,就是新增和删除元素的时候效率不高,由此出现了list和map等这种和数组具有相同功能的数据结构,我们称其为集合,他们底层的结构或是数组或是链表,总之是减少了数组的弊端。但是,他也有一个缺点,那就是存储的数据类型是任意的,无论是基本数据类型还是引用类型,这样带来的问题是,出现转型错误,例如:

public class Generic1 {

    public static void main(String[] args) {
        List list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add("3");

        for (int i = 0; i < list.size(); i++) {
            Integer a = (Integer) list.get(i);
        }

    }
}

在这段代码中,list存储了int和字符串类型数据,后面是把每个元素都转换成integer类型,很显然对应字符串来说会出现类型转换错误,但是这在编译阶段是无法发现的,这就可能使开发人员带来排错的困难和低效率。为了解决这种问题,便出现了泛型,它是jdk1.5有的。

​ 那么什么是泛型呢,其形式如下:

public interface List<E> extends Collection<E> //list接口
List<Integer> list = new ArrayList(); //使用时指定要存储的类型

我们可以看到用一个<>的形式来表示要存储的数据,并且这个数据类型是任意的,在使用时我们只要指定具体类型即可,说白了就是可以给一个集合贴上标签,指定其只能存什么,这就是泛型,它不断克服了存储任意数据类型的缺点,还增加了灵活性,如果在编写代码时不符合要求,那么会直接报错,便于排错。

泛型可以在哪些地方使用

泛型类

泛型类是指泛型定义在类上,用户使用的时候才把具体类型确定下来

public class Generic1 {

    public static void main(String[] args) {
        //指定具体类型
        mygGeneric<String> mygGeneric = new mygGeneric<String>(5,"my is Generic");
        System.out.println(mygGeneric.getT());
    }
}

class mygGeneric<T>{
    int anInt;
    T t; //可以这样直接使用

    public mygGeneric(int anInt, T t) {
        this.anInt = anInt;
        this.t = t;
    }

    public int getAnInt() {
        return anInt;
    }

    public void setAnInt(int anInt) {
        this.anInt = anInt;
    }

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }
}

泛型之间的继承关系

image-20201023101453201 image-20201023101638703

泛型接口

​ 泛型接口用法和类差不多

泛型方法

​ 泛型方法时独立的,与类是否使用了泛型没有关系

public static <U> U testGeneric(U t){
    System.out.println(t);
    return  t;
}

是对于U 的声明,必须显示声明,否则报错

类型通配符

public static void testGeneric2(List<?> t){
    System.out.println(t);

    for (int i = 0; i < t.size(); i++) {
        System.out.println(t.get(i));
    }
}

​ 使用?表示可以接受任意类型的参数,都是不能往里面写值,只能读取,因为泛型的存在就是为了确定要写入的数据类型的,?表示任意类型,所以无法写值。

通配符上限

类型通配符上限和下限

List<? extends Student>  list1 = null;  //上限
List<? super Person>  list2 = null; // 下限

List<Student> list3 = null;
List<Person> list4 = null;
list1 = list4; //会报错
list1 = list3;

list2=list3; //会报错
list2=list4;

类型通配符上限

​ 如果是List<? extends Student>这种类型,那么代表存储的元素只能是Student或Student的子类,而Person是Student的父类,所以list1 = list4会报错。

类型通配符下限

​ 如果是ListList<? super Person>这种类型,那么代表存储的元素只能是Person或Person的父类,而Student是Person的子类,所以list2 = list3会报错。

泛型擦除

​ 所谓反应擦除是指泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。也就是在运行时List还是会被解析为List,只不过在编译阶段确定了Object具体类型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值