1.22:java泛型

发布时间:2024年01月23日

泛型:

泛型类:

package fanxing;

public class fanxing <T>{
    private T data;
    public void fanxing(T addnum){
        this.data=addnum;
    }
    public T getData(){
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public static void main(String[] args) {
        fanxing fanxing1=new fanxing<>();
        fanxing1.setData("jiage");
        System.out.println(fanxing1.getData());
    }
}

在这里插入图片描述

泛型接口

在这里插入图片描述

泛型类的泛型只影响该类内的普通方法,若是泛型类()中声明了一个泛型方法(如),其可以是任意类型;可以类型与T同,也可以不同;

也可以限定类型变量,目的是让传入的两个变量均有某种方法便于比较等,如图为了使传入的参数均有compareTo方法,要注意这里均是写extends无论是派生类还是接口,先写类且只能有一个,再写接口

在这里插入图片描述

泛型的局限性

静态域或者方法里不能引用泛型方法【不可以定义静态泛型的变量】静态方法本身是泛型方法就行;

原因在于:泛型变量的类型实在类创建之后才清楚的。而静态变量的初始化在执行类的构造方法之前就执行了,因此虚拟机不知道其到底是什么类型;

静态方法本身是泛型方法就行;

不能实例化类型变量;

eg:this.data=new T();【错误的】

在定义泛型的时候不允许写基本的数据类型,只能写包装类,如int–>Integer;double–>Double;

原因是基本数据类型在jdk里不是对象;而泛型只允许是对象;

就算传入的泛型的类型不一样,同一个泛型类创建的对象getclass()获取的类是一样,即泛型类的原生类型;

可以定义泛型的数组,但不可以new进行初始化;

泛型类和异常结合的时候,对象是不可以被捕获的(无法被catch)

但通过特殊方式可以抛出;
在这里插入图片描述

继承关系:

若原本两个类具备继承关系,如animal为父类,dog为子类,若其作为泛型传入泛型类,那么泛型类的两个对象直接没有继承关系;即Pair和Pair之间没有任何的继承关系

Pair<animal> animalpair =new Pair<>();
Pair<dog> dogpair =new pair<>();

泛型类是可以扩展和继承其他泛型类的

fanxing<String> fanxing2= new ExtendsFanxing<String>();
private static class ExtendsFanxing<T> extends fanxing<T> {
}

为了便于使用,故而有了通配符

通配符

extends

不可以在类声明里用,只能在方法里用;<? extends fanxingsuper>

若遇到类中有set和get方法;

get方法只能在泛型为fanxingsuper的对象下使用,而set则是不允许被使用的,无论是fanxingsuper还是其子类;

super

此外有<? super fanxing>这意味着传入其中的是fanxing的超集,即fanxing自身以及其父类;

当前可以进行set,但只能传入fanxing及其子类,传入fanxingsuper报错;get方法获取值的时候,数据类型为Object

此外,可以通过该方式实现安全的写入数据;

虚拟机如何实现泛型的

对比于c#的泛型实现,c#中泛型无论是在程序源码中还是编译后的IL中,或是是在运行期CLR,都是实际存在的,List与List就是两个不同类;其在系统运行期生成,有自己的虚方法表和类型数据,这种实现为类型膨胀,基于这种方法实现的泛型称为真实泛型;

而java中的泛型只在程序的源码中存在,在编译后的字节码文件中就已经替换为原来的原生类型(裸类型)了,并在相应的地方插入了强制转型的代码;对于运行期的java而言,ArrayList与ArrayList是同一个类,因此泛型技术实际上是Java语言的一颗语法糖;其泛型的实现方法称之为类型擦除,基于这种方法实现的泛型称为伪泛型;

由于java泛型的引入,虚拟机也有所调整,引入了signature,localvariableTypeTable等新的属性。Signature是其中最重要的一项属性,作用是存储一个方法在字节码层面的特征签名;该属性中保存的参数类型不是原生类型,而是包括了参数化类型的信息。修改后的虚拟机规范要求所有能识别49.0以上版本的class文件的虚拟机都能要能正确的识别Signature参数;

一项属性,作用是存储一个方法在字节码层面的特征签名;该属性中保存的参数类型不是原生类型,而是包括了参数化类型的信息。修改后的虚拟机规范要求所有能识别49.0以上版本的class文件的虚拟机都能要能正确的识别Signature参数;

由此,从signatur属性的出现可以得出结论,擦除法所谓的擦除其实只是对方法的Code属性中字节码进行擦除,实际上元数据中还是保留了泛型信息,这也是我们能通过反射手段取得参数化类型的根本依据。

文章来源:https://blog.csdn.net/qq_60637458/article/details/135760681
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。