博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA当中的泛型
阅读量:4150 次
发布时间:2019-05-25

本文共 3566 字,大约阅读时间需要 11 分钟。

JAVA泛型其实是类型的类型,比如List数组我们可以接受任意类型的元素存储在数组当中,也可以在定义数组时,指定集合当中只存储某一类型。可以说泛型给我们的程序代码提供了可扩展性。

关于泛型的声明,如何使用,这篇暂不介绍,我们从比较容易困惑的地方开始

<? extend T> T可以是任意具体类型

举个例子如果我们定义了一个方法,接受List<Number> 类型的参数,那我们是否可以传递List<Integer>进去,答案是否定的

<? extend T> 表示的是当前泛型当中的元素,必须是T或者T类型的子类或者实现类

我们来看个例子,以下是三个类型的继承关系

class Fruit{}class Apple extends Fruit{}class Orange extends Fruit{}
public class Test {    public static void main(String[] args) {        List
apples = new ArrayList<>(); apples.add(new Apple()); List
fruits = new ArrayList<>(); fruits.add(new Fruit()); Test.Transfer
transfer = new Test.Transfer
(); Fruit f1 = transfer.transfer(apples); Fruit f2 = transfer.transfer(fruits); } static class Transfer
{ T transfer(List
list) { return list.get(0); } }}

这里我们给出了一个静态内部类,用来转化,传入的是List对象,获取到List当中的元素,因为List当中存放的元素都是T类型的子类,所以我们在返回值上设定为T,是没有问题的

但是有个新的问题,如果我们想往List<? extends Fruit>当中添加元素时,却不能添加成功

List
fruits = new ArrayList
(); fruits.add(new Fruit()) //编译不通过

原因在于,当我们往集合当中添加元素时,因为集合的声明是Fruit的子类,所以我们并不清楚是具体的那个子类,Apple或者是Fruit,这个时候编译器就会提示报错了,接下来就是关于泛型的另外一个使用方式了

<? supper T>表示集合当中存放的必须是T类型或者T以上的父类型

public class Test {    public static void main(String[] args) {        List
fruits = new ArrayList<>(); List
apples = new ArrayList<>(); Test.Transfer transfer = new Test.Transfer
(); transfer.transfer(fruits,new Apple()); transfer.transfer(apples, new Apple()); } static class Transfer
{ void transfer(List
list,T item) { list.add(item); } }}

基于以上方式实现,就可以在数组当中添加不同的类型

总结 extends 和 supper 一个是用来查询集合当中的元素,另一个是用来往集合当中添加元素

类型擦除

泛型当中如果我们定义的是Node<T> 那么编制出来的T就是Object, 如果是 ? extends List 那么编译出来就是List

1、JAVA当中不允许创建泛型类型的数组

Object[] list = new String[2];        list[0] = "abc";        list[1] = 123;

上面这段代码我们在编译时是没有问题的,但是当执行的时候,就会抛出类型转换异常,原因是String类型的数组不能存放整形

如果我们定义的集合是List[] list = new ArrayList<String>[];

但是在存放数据时,保存的是list[0] = new ArrayList<Integer>; list[1] = new ArrayList<String>; 因为java当中存在类型擦除,所以ArrayList<String> 和ArrayList<Integer> 是一样的!为了避免这种问题发生,所以就不允许创建泛型类型的数组。

2、对于泛型代码,JAVA编译器会生成一个bridge method 

public class Node
{ public T data; public Node(T data) { this.data = data; } public void setData(T data) { System.out.println("set Node data"); this.data = data; } public static void main(String[] args) { MyNode myNode = new MyNode(5); Node node = myNode; node.setData("adb"); //抛出异常 }}class MyNode extends Node
{ public MyNode(Integer data) { super(data); } public void setData(Integer data) { System.out.println("set myNode data"); super.data = data; }}

上面这段代码在编译时是可以的,但是运行时就会抛出异常错误,原因在于在MyNode方法当中编译时会生成一个BridgeMethod

class MyNode extends Node {    // Bridge method generated by the compiler    public void setData(Object data) {        setData((Integer) data);    }    public void setData(Integer data) {        System.out.println("MyNode.setData");        super.setData(data);    }    // ...}

这就是为什么不能转化String为Integer的原因

3、关于泛型使用instanceOf

我们无法对泛型代码直接使用instanceof ArrayList<Integer> 因为对编译器来说ArrayList<Integer>和ArrayList<String>是同一个类型,如果我们想判断是否为ArrayList的话,可以通过这种方式来调用

public static void rtti(List
list) { if (list instanceof ArrayList
) { // OK; instanceof requires a reifiable type // ... }}
以上就是关于泛型的一些内容,如有问题欢迎指正

转载地址:http://vlvti.baihongyu.com/

你可能感兴趣的文章
iOS菜鸟学习—— NSSortDescriptor的使用
查看>>
CORBA links
查看>>
如何使用BBC英语学习频道
查看>>
初识xsd
查看>>
java 设计模式-职责型模式
查看>>
构造型模式
查看>>
svn out of date 无法更新到最新版本
查看>>
java杂记
查看>>
RunTime.getRuntime().exec()
查看>>
Oracle 分组排序函数
查看>>
删除weblogic 域
查看>>
VMware Workstation 14中文破解版下载(附密钥)(笔记)
查看>>
日志框架学习
查看>>
日志框架学习2
查看>>
SVN-无法查看log,提示Want to go offline,时间显示1970问题,error主要是 url中 有一层的中文进行了2次encode
查看>>
NGINX
查看>>
Qt文件夹选择对话框
查看>>
DeepLearning tutorial(5)CNN卷积神经网络应用于人脸识别(详细流程+代码实现)
查看>>
DeepLearning tutorial(6)易用的深度学习框架Keras简介
查看>>
DeepLearning tutorial(7)深度学习框架Keras的使用-进阶
查看>>