Java泛型基础

动机和优点

从JDK1.5开始,Java允许定义泛型类、泛型接口、泛型方法,使用泛型可以在程序编译时检测出错误,而不是运行时,提高了程序的可靠性和可读性。

例如,创建一个字符串的list

List<String> list = new ArrayList<>();

我们只能往这个list中添加字符串,例如:

list.add("abc");

如果添加非字符串,程序就会产生编译错误。

定义和使用泛型类

泛型的类型必须是引用类型,不能使用int、char、double这样的基本类型

有多个参数的泛型类: <E1, E2, E3>

泛型方法: 将泛型类型放在关键字static之后,public void static "<"E> func (E[] list)

受限泛型类型:"<"E extends xxx>

非受限泛型:"<“E> 等同于”<"E extends Object>

  • 自动打包
List<Integer> intList = new ArrayList<>();
intList.add(1);

Java自动将1包装成new Integer(1)

  • 自动拆箱
List<Integer> intList = new ArrayList<>();
intList.add(1);
int a = intList.get(0);

Java将包装类型1自动拆箱赋给基本变量a

通配泛型

通配泛型有三种形式,?、? extends T、super extends T,其中T是泛型类型

  • ?: 非受限通配,等同于? extends Object
  • ? extends T: 受限通配,表示T的子类型
  • super extends T: 上限通配,表示T的父类型

消除泛型

泛型是通过类型消除来实现的,编译器在编译阶段消除泛型类型,因此泛型在运行阶段是不可用的。

泛型存在于编译时,编译器确认泛型安全使用,然后把它转换成原始类型,例如下面两段代码展示了泛型编译前后的变化

ArrayList<String> list = new ArrayList<>();
list.add("abc");
String state = list.get(0);
ArrayList list = new ArrayList();
list.add( "abc");
String state = (String) (list.get(0));

对泛型的限制

由于泛型类型在运行时被消除,因此对于如何使用泛型类型是有一些限制的。下面是其中的一些限制

  1. 不能使用new E()

不能使用泛型类型参数创建实例。

例如,下面的语句是错误的: E object = new E();

出错的原因是运行时执行的是new EO),但是运行时泛型类型E是不可用的。

  1. 不能使用new E[]

不能使用泛型类型参数创建数组。

例如,下面的语句是错误的: E[] elements = new E[capacity];

  1. 在静态上下文中不允许类的参数是泛型类型

由于泛型类的所有实例都有相同的运行时类,所以泛型类的静态变量和方法是被它的所有实例所共享的。因此,在静态方法、数据域或者初始化语句中,为类引用泛型类型参数是非法的。

  1. 异常类不能是泛型的

泛型类不能扩展java.lang.Throwable,因为如果允许这样做,就应添加一个catch子句,JVM必须检查这个从try子句中抛出的异常以确定它是否与catch子句中指定的类型匹配。但这是不可能的,因为在运行时类型信息是不可得的。

小结

1.泛型具有参数化类型的能力。可以定义使用泛型类型的类或方法,编译器会用具体类型来替换泛型类型。

2.泛型的主要优势是能够在编译时而不是运行时检测错误。

3.泛型类或方法允许指定这个类或方法可以带有的对象类型。如果试图使用带有不兼容对象的类或方法,编译器会检测出这个错误。

4.定义在类、接口或者静态方法中的泛型称为形式泛型类型,随后可以用一个实际具体类型来替换它。替换泛型类型的过程称为泛型实例化。

5.不使用类型参数的泛型类称为原始类型,例如 ArrayList。使用原始类型是为了向后兼容Java较早的版本。

6.通配泛型类型有三种形式: ?、? extends T和 ? super T,这里的T代表一个泛型类型。第一种形式?称为非受限通配,它和? extends 0bject是一样的。第二种形式? extends T称为受限通配,代表T或者T的一个子类型。第三种类型? super T称为下限通配,表示T或者T的一个父类型。

7.使用称为类型消除的方法来实现泛型。编译器使用泛型类型信息来编译代码,但是随后消除它。因此,泛型信息在运行时是不可用的。这个方法能够使泛型代码向后兼容使用原始类型的遗留代码。

8.不能使用泛型类型参数来创建实例。

9.不能使用泛型类型参数来创建数组。

10.不能在静态环境中使用类的泛型类型参数。

11.在异常类中不能使用泛型类型参数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jeff_Xxxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值