java 泛型 基本知识

1 泛型

泛型就这么简单 - SegmentFault 思否

在定义属性、方式时,有一些数据无法确定数据类型,只有在使用时,才能知道是什么类型。
此时就可以用泛型来代指这些数据类型,泛型可以看做一个占位符,运行时会被替换成实际放置的数据类型。
泛型可以用任意的字符来表示,但是通常约定如下,实际情况要根据开发逻辑使用,正确的名字能增强代码可读性。

E 代表entity 说明这里输入的是实体对象,不是String或者Data
T 代表type类型
K 代表key
V 代表value

泛型存在以下优点:

  1. 数据安全性,传递数据时,数据类型确定,不会出现多种数据
  2. 不需要强制类型转换
  3. 泛型常用于和反射组合,实现封装基础操作的目的,提高代码的复用性

1.1 泛型类

泛型类有三种情况

1.1.1 成员变量为泛型时

在当前类中某一个成员变量在定义时不确定数据类型,那么这个类需要定义为泛型类型,需要在类名后用 <通配符> 加以修饰

public class 类名 { 方法体 }

此时类中的成员变量如果需要定义为泛型,那么可以用同样的通配符 T 修饰说明变量是一个泛型变量
此时成员变量的get/set写法如图,可以看到就是将原来确定的数据类型换成了T,其他没有变化
image

1.1.2 方法返回值为泛型时

除了在定义时设置泛型变量必须设置泛型类,在获取某个方法的返回值时如果定义了泛型变量,也必须将类改为泛型类
image

1.1.3 继承的父类为泛型时

当子类继承父类时,父类是一个泛型类,那么子类也必须使用泛型

  • 父类使用了泛型
    image

  • 子类跟着使用泛型
    image

1.2 泛型方法

在类里如果存在一个参数或返回值的类型不确定的方法,此时就需要使用泛型来标明方法的参数表和返回类型,这种方法就叫泛型方法。
此时的类可以设定为泛型类也可以不设定,非泛型的类可以在泛型方法上加static,泛型的类不可以在泛型方法上加static

public ( T|void) 方法名(T 参数名){ return 值; }

根据返回类型有四种常见的泛型方法:

void 无返回值时
T 返回类型为对象
List 返回类型为List集合
<K,V> Map<K,V> 返回类型为Map集合

举例:
image

1.3 泛型接口

在接口中定义抽象方法时,还不能确定方法的参数表类型,此时的接口可以定义为一个泛型接口,方法则依据泛型方法来书写
image

此时实现类可以使用任意数据类型,由实现类自己定夺
image

在实现接口之后,也不能确定T的数据类型,那么这个实现类需要定义为泛型类
image

1.4 上限和下限通配符

通配符即 "?",也是泛型的字符,只是约定由 "?"表示JAVA类中所有的数据类型,代指“这个地方可以放任何东西,对象、类型、K值、V值都可以”

有时候我们希望泛型不那么自由,有一定的限制,只能放某些类的子类或者某些类的父类,此时就可以设置上限和下限通配符

1.4.1 上限通配符 ? extends A

设置?的上限类型为A 此时只能传入A或A的子类或子类的子类等 不能传入A的父类比如超级父类object这种
传入的数据类型?的上限只能为A
image

1.4.2 下限通配符 ? super A

设置?的下限类型为A 此时只能传入A或A的父类 不能传入A的子类
传入的数据类型?的下限只能为A
image

1.4.3 实际调用场景

实际调用时,只看传入的数据本身设置的类型是否符合通配符设定,不会去看数据中存放的子数据是否符合通配符设定。
回顾一个知识点:向上造型,子类的对象可以指定给父类的变量,因此集合指定了存储的数据类型为某个元素A后,可以存入元素A以及A的子类B,甚至是B的子类C

实例1
设置一个list 存放了元素A以及A的子类元素B
此时调用的方法可以是上限通配符也可以是下限通配符,因为两种方法都只看list集合设置时定义的元素类型,不去看传入的集合中实际储存的对象的类型

假如要看实际储存的对象的类型,那么show3会报错——show3不允许存入Userinfo类的数据
image

实例2:
设置一个list 允许存放所有类型的元素 因为这是一个object类的list
此时只存放一个ParentEntity类的元素
此时调用的方法只能是下限通配符,另一个方法会报错——因为只允许存入ParentEntity和其子类,即便这个集合中存入了一个ParentEntity类的数据
再次印证了方法只看传入的数据类型,不去看数据中存储的数据类型的设定
image

posted @ 2021-08-12 22:46  夏·舍  阅读(81)  评论(0编辑  收藏  举报