Java---泛型

文章介绍了Java中泛型的概念和重要性,从使用Object类型数组的问题出发,解释了泛型如何解决类型安全和强制转换的问题。泛型在编译时期检查元素类型并避免运行时的类型转换,其擦除机制保证了运行时的兼容性。此外,文章还提到了泛型方法和泛型的上界约束,帮助理解泛型的更广泛应用。
摘要由CSDN通过智能技术生成


先拿数组举例子吧:

int[]arr=new int[10];
String[]arr=new String[10];

之前我们创建数组,数组的类型都是要自己指定,那我们现在就想着能不能有一种语法,可以让我们把数组类型作为参数,传递什么类型,数组就是什么类型,这就是泛型的农民版概念.

Object类型

我们不止一次提及过,Java中所有的类默认继承了Object类,也就是说Object是所有类的父类,我们实现可不可以通过Object的兼容性做些事情:

class MyArray{
    //        public int[]arr=new int[10];
    Object[]objects=new Object[10];

    public void add(int pos,Object val){
        objects[pos]=val;
    }

    public Object get(int pos){
        return objects[pos];
    }
}
public class Generic {

    public static void main(String[] args) {
        MyArray myArray=new MyArray();
        myArray.add(0,'a');
        myArray.add(1,1);
        myArray.add(2,1.1);
        myArray.add(3,"手");
        char arr1=myArray.get(0);
    }
}

在这里插入图片描述
正如我们刚才所说的,利用了Object的兼容性,object[ ] 这个数组海纳百川,无论是什么类型,我都照收不误,但是麻烦的地方在于当我们想要获取到数组中的元素的时候,每一次都要进行强制类型转换:
在这里插入图片描述我们在给数组填充元素的时候,是把别的类型变成了Object类型,这其中涉及到了装箱的操作,现在我们的这一步强制类型转换,就是把一个Object类型向下转型,其中也是会涉及到拆箱的操作.
那么问题来了,难道每一次我们想要使用数组里元素的时候,都需要进行强制类型转换吗?现在数据小我们吃点苦头没关系,如果现在这是一个十分庞大的数组,难道我们还要手动一个个查看类型然后再一个个强制转换吗?这在全面现代化的今天,显然是不符合时代潮流的,未来一定是向着解脱人类这个方向发展的,人生下来的意义不在于享受苦难.
我们不妨思考一下,会出现这样问题的原因就在于,我们在存储元素的时候,由于Object类型太兼容了,所以我们存进去的类型是五花八门的,如果我们规定只能存放某一种类型的元素,那是不是就不必进行那么繁琐的操作了?至于说我们想要的是那种类型,全看我们传入的参数类型,这就是我们接下来要讲解的泛型!

泛型认识

class MyArray<E>{//我们class一个类的时候在类名的后面可以加上<>代表这是一个泛
//型类,<E>里面的这个E并没有特殊的语法含义,只是一个标志,E[]代表这是一个E类型的数
//组,T t代表t这个变量是T类型,还有就是K,V这一对符号.<>里面可以放多个符号,那么
//对应到实例化泛型类的时候<>里面也要放相同数目的元素,并且符号和类型一一对应

    E[]objects=new Object[10];//这一行现在会报错,因为向下转型并不安全
    //我们现在可以这样写:
    //E[]objects=(E[])new Object[10];

    public void add(int pos,E val){//E就代表你传入的这个类型
        objects[pos]=val;
    }

    public E get(int pos){
        return objects[pos];//可以直接返回的原因是:object数组本身就是E类型
        //里面的元素自然也是E类型的,可能有同学会奇怪的原因在于,object指向的
        //是一个由Object[]强转过来的数组,我想说的是,站在编译器的角度,你创
        //建的数组实际上就是一个E类型的数组了,而且数组中的每个元素都必须是E类型
    }
}
public class Generic {

    public static void main(String[] args) {
        MyArray<Integer> myArray=new MyArray<>();
        myArray.add(0,0);
        myArray.add(1,1);
        myArray.add(2,2);
        int a1=myArray.get(0);
        
    }
}

泛型的意义

1.检查元素类型(通过add函数中的E类型的参数来限制,如果不是E类型,是会爆红的)
2.强制类型转换(不需要我们手动强制转换了,通过get的返回值E来帮助)

擦去机制

泛型仅仅是编译时期的一种语法,言外之意就是在运行期间是没有泛型这一说的,运行时所有的E都会被擦成Object,我当时最大的一个问题就是:如果在运行时所有的E都变成了Object,那我们泛型在编译期间做的事情不就白费了吗:

int a1=myArray.get(0);

就比如这个:get方法原本的返回类型是E(Integer),现在被擦成了Object,这里为什么还是可以通过?
后来我查阅了相关资料,发现:Jvm在暗地里默默地记录下了原本的E类型,等到被擦成object时,还是可以找到原来的类型的,我也询问了我的老师,我的老师就很明确地告诉了我,如果实在不能理解,也没有必要强求清楚到底发生了什么,这并不会影响我们对于泛型的使用.

泛型方法

刚才我们都是在说泛型类,那我们可不可以在一个方法上面使用泛型这个知识点呢?

class A{
    public  <E>void func(E val){
        System.out.println(val);
    }
}

大致就是这样子使用,在这里也不必刻意传入E的具体类型,直接传入参数,会有专业的对象根据参数自动识别这个E类型的.

泛型的上界

我们说的泛型的上界,可以参考于之前的集合关系图,自上向下就是广义上的父类子类的关系,上界就说明这个泛型类是这个上界的一支,必须是这一脉下面的:
在这里插入图片描述

在这里插入图片描述
这里报错的原因很简单,就是因为Integer并没有继承A这个类,所以不是一家人,不进一家门!

好了,兄弟们,这就是关于泛型,我想给大家分享的知识点,希望能够对大家起到一定的帮助!
百年大道,你我共勉!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值