1. Java中的泛型

作者: Shimmer_ | 来源:发表于2021-04-21 23:36 被阅读0次
image

泛型:参数化类型,就是将原来具体的类型参数化

我们定义方法时有形参,在实际调用该方法时我们会传递实参

相应的,我们在定义方法或类时指定一个泛型(类型形参),在具体使用时传入具体的类型(类型实参)

1. 为什么需要泛型

在日常开发过程中,我们可能需要根据数据的类型写大量逻辑重复的代码,又或者为了规范操作,封装统一的表面使用逻辑等,使用泛型来完成上述操作

例如数据结构当中,数据作为对象存储在各种结构当中,这里我们忽略数据本身的类型,只在乎它数据与数据间的关系,只处理增删改查等操作;如果不使用泛型,那么就得在使用时为特定类型而编写一个对应的数据结构了

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable 
...

又例如在Android开发当中,会经常使用到ListView、RecyclerView控件显示多项数据,他们的共性大都有上下滚动、点击跳转,在为它编写适配器时如果不使用泛型,那么数据源发生一点改变,直接导致原有的类不能复用,需要编写新的类,使用泛型之后则只需要在对itemview填充时增加判断即可

或许会有疑惑为什么不能直接用object来代替泛型,在使用时进行强转,这样也可以,但我们会有很多重复的类型判断代码,这样显得凌乱,甚至更繁杂。

其实Java中的泛型实现就是上面这样实现的。可以看最后的虚拟机实现泛型

2. 泛型的优点

  • 适用于多种数据类型执行相同的代码
  • 泛型中的类型在使用时指定,不需要强制类型转换,同时还能避免传入类型错误

3. 定义泛型

泛型类

public class GenericityClass<T, E, K, V> {
    T t;
    E e;
    K k;
    V v;
}

泛型接口

public interface GenericInterface<T, E, K, V> {
    T getT();
    E getE();
    K getK();
    V getV();
}

泛型方法

泛型方法可以独立使用,不强制在泛型类或接口中

public static <T> T genericStaticMethod(T t){
    return t;
}
public <T> T genericMethod(T t){
    return t;
}
//使用
String s = new GenericDemo().genericMethod("泛型");
Object o = new GenericDemo().<Object>genericMethod("泛型");

泛型的声明可以使用任意的大写字符,但前后需要匹配,同时需要使用常用或者说默认的字母来定义泛型

4. 使用泛型

限定类型变量

extends: 限定泛型具有或实现的功能 后面可接一个类&多个接口,类必须写在最前且只有一个

通配符类型 ?

  • ?extends T:用于传入数据

    • 解决泛型子类代替父类的问题

    • 只用于方法

    • 用于安全的访问数据

    • 表示传入类型的上级

  • ?super T:用于获取数据(获取的是object)

    • 定义传入的参数的下界

    • 不能传入T的子类,只能是T或T的父类

    • 用于安全的写入数据

    • 表示传入类型的下级

  • 无限定的通配符 ?

    • 表示对类型没有什么限制,可以把?看成所有类型的父类
    • 一般是方法中,只是为了说明用法

继承规则

  • 泛型类中泛型不能使用 子类代替父类的形式
  • 泛型类可以继承扩展其他泛型类

泛型中约束和局限性

  • 不能实例化类型变量:使用时需要传入具体的类型
  • 静态域或方法不能引用类型变量(静态方法本身是泛型方法也可以):泛型类的静态上下文中类型变量失效,因为泛型是需要对象加载时才知道是什么类型
  • 只允许传入包装类
  • 不能使用 instance of
  • 运行时类型查询只适用于原始类型:getclass获取的类名是原生泛型类类型,与传入参数类型无关
  • 不能对泛型 创建数组 new R<T>[10];
  • 不能派生异常(Exception Throwable)因为不能捕获泛型异常对象
    但是可以捕获异常,抛出泛型

5. 虚拟机如何实现泛型的

JDK1.5以前没有泛型的概念

Java的泛型是通过泛型擦除实现的

javac编译时会进行泛型擦除,泛型被定义为Object,这种方式称为伪泛型;在使用时会进行类型强转,所以泛型只在程序源码中存在,在编译后的字节码文件中,就已经替换为原来的原生类型(Raw Type,也称为裸类型)了,并且在相应的地方插入了强制转型代码,因此,对于运行期的Java语言来说,ArrayList<int>与ArrayList<String>就是同一个类,所以泛型技术实际上是Java语言的一颗语法糖,Java语言中的泛型实现方法称为类型擦除,基于这种方法实现的泛型称为伪泛型

语法糖

糖衣语法,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会

相关文章

  • 泛型(一)

    1. Java中的泛型是什么 ? 使用泛型的好处是什么? 泛型是Java SE 1.5的新特性,泛型的本质是参数化...

  • 泛型常见的面试题

    1. Java中的泛型是什么 ? 使用泛型的好处是什么? 这是在各种Java泛型面试中,一开场你就会被问到的问题中...

  • JAVA泛型的理解

    泛型大家都接触的不少,但是由于Java历史原因,Java中泛型一直被称为伪泛型,因此对Java中的泛型,有很多不注...

  • 带你Dart带你Diao之泛型

    泛型学过Java的都应该比较熟悉了,Dart的泛型和Java泛型的核心理念都差不多,在使用中略有不同。 1.使用泛...

  • 泛型依赖注入

    泛型依赖注入 1.定义泛型 Java代码: 2.实现基类,声明泛型 Java代码: xml代码:

  • Kotlin 泛型

    Kotlin 支持泛型, 语法和 Java 类似。例如,泛型类: 泛型函数: 类型变异 Java 的泛型中,最难理...

  • 1. Java中的泛型

    泛型:参数化类型,就是将原来具体的类型参数化 我们定义方法时有形参,在实际调用该方法时我们会传递实参相应的,我们在...

  • Java泛型教程

    Java泛型教程导航 Java 泛型概述 Java泛型环境设置 Java泛型通用类 Java泛型类型参数命名约定 ...

  • 泛型学习

    1.泛型是Java中参数化类型的方式。将类型也作为一种参数进行传递。2.它有泛型的方法,泛型参数,泛型类。3.泛型...

  • Java泛型

    参考:Java知识点总结(Java泛型) 自定义泛型类 自定义泛型接口 非泛型类中定义泛型方法 继承泛型类 通配符...

网友评论

    本文标题:1. Java中的泛型

    本文链接:https://www.haomeiwen.com/subject/mawtrltx.html