当前位置: 首页 > news >正文

泛型的相关知识

定义类、接口、方法时,同时声明了一个或多个类型变量(如:<E>),称为泛型类、泛型接口、泛型方法,他们统称为泛型

public class ArrayList<E>{ //... }

作用:泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力,这样可以避免强制类型转换,及其可能出现的异常。

泛型的本质:把具体的数据类型作为参数传递给类型变量。

为什么要使用泛型

先来看我们不使用泛型时往集合中添加元素有什么问题

import java.util.ArrayList; import java.util.Iterator; public class Test { public static void main(String[] args) { //1.创建集合的对象 ArrayList list = new ArrayList(); //2.添加数据 list.add(123); list.add("aaa"); list.add(new Student("zhangsan", 21)); //3.遍历集合,获取里面的每一个元素 Iterator it = list.iterator(); while (it.hasNext()) { Object obj = it.next(); System.out.println(obj); } } }

输出结果:

当你往ArrayList集合中添加数据时,调用add()方法,会显示添加的数据是Object类型,也就是什么类型都可以添加,比如int类型、String类型,甚至是自己定义的Student类型,使用iterator()迭代器遍历集合中的元素,用next()方法拿到的元素也是Object类型的,我们可以将其打印输出,没有问题。但是,多态的弊端是不能访问子类特有的功能,比如我想打印输出第二个元素"aaa"的长度,这是一个String类型的数据,直接使用obj.length()来输出长度,但其实这样写是会报错的,编译就不通过

那如果强制转换

你会发现编译通过了,语法没有问题,但是运行会报错。

报了一个类型转换异常,为什么会报这个异常呢?

如果你是int类型转成String类型那没问题,但是遍历的是数组中的整个元素,自定义的Student类型怎么转成String类型呢,所以会报一个类型转换异常。

通过以上现象我们发现,当往集合中添加任意类型元素时,不能访问子类特有的功能,如果使用强制类型转换则可能会出现类型转换异常,所以使用泛型来解决这个问题。

import java.util.ArrayList; import java.util.Iterator; public class Test { public static void main(String[] args) { //1.创建集合的对象 ArrayList<String> list = new ArrayList(); //2.添加数据 // list.add(123); list.add("aaa"); list.add("bbb"); list.add("ccc"); // list.add(new Student("zhangsan", 21)); //3.遍历集合,获取里面的每一个元素 Iterator<String> it = list.iterator(); while (it.hasNext()) { String str = it.next(); System.out.println(str); } } }

使用泛型<String>来规定ArrayList数组中的数据类型只能是String类型,这样就保证了数组中数据类型的统一,把运行时期的问题提前到了编译时期,避免了强制类型转换可能出现的异常。

泛型的分类

前面提到,在定义类、接口、方法时,同时声明了一个或多个类型变量(如:<E>),称为泛型类、泛型接口、泛型方法,泛型也就分为这三类,每类都各自有各自的格式。

泛型类

格式:

修饰符 class 类名<类型变量,类型变量,...> {

}

public class ArrayList<E>{ ... }

类型变量建议用大写的英文字母,常用的有:E、T、K、V

自定义泛型类

自定义泛型类——声明单个

public class MyArrayList<E> { private Object[] arr = new Object[10]; private int size;//记录当前位置的 public boolean add(E e){ arr[size++] = e; return true; } public E get(int index){ return (E) arr[index]; } }

自定义泛型类——声明多个

public class MyClass1<E, T> { public void put(E e, T t){ } }

自定义泛型类——必须要继承某个类

public class MyClass2<E extends Animal> { }

泛型接口

格式:

修饰符 interface 接口名<类型变量, 类型变量, ...>{
}

public interface A<E> { ... }

举例:

public interface Data<T> { void add(T t); ArrayList<T> getByName(String name); }

泛型方法

格式:

修饰符 <类型变量, 类型变量, ...> 返回值类型 方法名(形参列表) {

}

public static <T> void test(T t) { }

注意这个下面这个不是泛型方法:

public E get(int index) { return (E) arr[index]; }

补充知识

拓展知识:

当你在java文件中使用了泛型来限制数据类型,但当这个java文件编译成class文件后就没有你写的泛型了,统一当成Object类型处理,只是当你往外取数据时,底层会帮你再次强转成你所定义的泛型。

泛型的细节:

  1. 泛型是工作在编译阶段的,一旦程序编译成class文件,class文件中就不存在泛型了,这叫做泛型擦除
  2. 泛型不支持基本数据类型,只能支持对象类型(引用数据类型)。
  3. 指定泛型的具体数据类型后,传递数据时,可以传入该类类型或者其子类类型
  4. 如果不写泛型,默认是Object类型

通配符

就是“?”,可以在“使用泛型”的时候代表一切类型;

E T K V是在定义泛型的时候使用。

泛型的上下限

泛型上限:? extends A:?能接收的必须是A或者是A的子类

泛型下线:? super A:?能接收的必须是A或者是A的父类

http://www.cnnetsun.cn/news/42093.html

相关文章:

  • 全网最全的软件测试面试八股文(含真题答案+文档)
  • OpenResume专业简历制作工具完整使用指南
  • springboot肿瘤患者康复回访系统_109a2sb0-
  • 【KL 散度】深入理解 Kullback-Leibler Divergence:AI 如何衡量“像不像”的问题
  • 5分钟掌握LIBERO:开启终身机器人学习的革命性平台
  • 文件上传革命:jQuery File Upload如何让开发效率飙升500%
  • SolidWorks三维模型与工程图差距分析介绍
  • COMSOL模拟锌离子电池锌负极电场模型教程:从零开始构建并详细解析源文件,适合初学者的电场建模教学
  • 终极指南:如何用PIKE-RAG打造领域专属的智能问答系统
  • 5分钟从文档小白到OCR专家:Zerox如何让文字识别变得像拍照一样简单
  • RocketMQ如何防止消息丢失?
  • CSS尺寸、盒子模型、定位、浮动与布局(Flex/Grid)
  • 《构建游戏实时流失预警模型的核心逻辑》
  • 两个步骤,打包war,tomcat使用war包
  • idea修改maven的刷新引入依赖快捷键
  • 纯电动汽车Simulink仿真模型建模详细步骤。 通过文档的形式,跟着文档一步一步操作,既可以...
  • 同花顺平衡多空看图操作多空理论
  • 通达信222222测试帖别下载
  • 通达信大盘个股共振指标公式
  • 这些核心特征,让芯片散料转编带设备成行业刚需
  • ~给媳妇的新称呼~
  • java计算机毕业设计社区服务微信小程序 基于微信生态的社区便民服务平台 SpringBoot+微信小程智慧社区服务系统
  • SynthPose-VitPose终极部署指南:从零到精通的人体姿态估计实战
  • DataEase vs PowerBI:当数据分析遇见选择困难症,你该如何破局?
  • android 之 AAudio
  • anoconda简单操作
  • 多场景头盔佩戴检测
  • 70看看:AI如何帮你快速生成代码项目
  • 13、Puppet 模块与类:从基础到高级应用
  • JBoltAI 识图阅卷:AI 赋能教育考评,开启智能阅卷新时代