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

[Java] 泛型

目录

1、初识泛型

1.1、泛型类的使用

1.2、泛型如何编译的

2、泛型的上界

3、通配符

4、通配符上界

5、通配符下界


1、初识泛型

泛型:就是将类型进行了传递。从代码上讲,就是对类型实现了参数化。

泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译器去做检查

语法:

class 泛型类名称<类型形参列表> {
        // 这里可以使用类型参数
}
class ClassName<T1, T2, ..., Tn> {
}

class 泛型类名称<类型形参列表> extends 继承类 /* 这里可以使用类型参数 */ {
        // 这里可以使用类型参数
}
class ClassName<T1, T2, ..., Tn> extends ParentClass<T1> {
        // 可以只使用部分类型参数
}

例:创建一个泛型数组

class MyArray <T> {//public T[] array = new T[10]; // 1//public T[] array = (T[]) new Object[10];public Object[] array = new Object[10];// 不考虑pos非法情况,默认合法public void setValue(int pos,T val) {array[pos] = val;}public T getValue(int pos) {return (T)array[pos];//把返回的类型 强转为指定类型}public Object[] getArray() {return array;}
}
public class Test {public static void main(String[] args) {public static void main(String[] args) {MyArray<Integer> myArray = new MyArray<>();//2myArray.setValue(0,10);myArray.setValue(1,12);int ret = myArray.getValue(1);//3System.out.println(ret);myArray.setValue(2,"abc");//4MyArray<String> myArray2 = new MyArray<>();myArray2.setValue(0,"abcd");myArray2.setValue(1,"efg");String ret = myArray2.getValue(1);System.out.println(ret);}
}

代码解释:

1. 类名后的<T>代表占位符,表示当前类是一个泛型类

   类型形参一般使用一个大写字母表示,常用的名称有:

  • E 表示 Element
  • K 表示 Key V 表示 Value
  • N 表示 Number
  • T 表示 Type
  • S, U, V 等等 - 第二、第三、第四个类型

2. 注释1处,Java中不允许new一个泛型类型数组

  • 意味着 T[] ts = new T[5]; 是不对的
  • T[] array = (T[])new Object[10]; 这个方式也不太好
  • 推荐这种方式 Object[] array = new Object[10];

3. 注释2处,类型后加入<Integer>指定当前类型

4. 注释3处,不需要进行强制类型转换

5. 注释4处,代码编译报错,此时因为在注释2处指定类当前的类型,此时在注释4处,编译器会在存放元素的时 候帮助我们进行类型检查。

1.1、泛型类的使用

语法:

泛型类<类型实参>变量名;// 定义一个泛型类引用

new泛型类<类型实参>(构造方法实参);// 实例化一个泛型类对象

示例:

MyArray<Integer> list = new MyArray<Integer>();

注意:泛型只能接受类,所有的基本数据类型必须使用包装类!

类型推导:

当编译器可以根据上下文推导出类型实参时,可以省略类型实参的填写

MyArray list = new MyArray<>(); // 可以推导出实例化需要的类型实参为 Integer

1.2、泛型如何编译的

泛型是编译时期存在的,当程序运行起来到JVM之后,就没有泛型的概念了,编译器生成的字节码在运行期间并不包含泛型的类型信息。

泛型在编译的时候如何编译的呢?

答:在编译的过程当中,将所有的T替换为Object这种机制,我们称为:擦除机制

注:Java的泛型机制是在编译时期实现的。编译器生成的字节码在运行期间并不包含泛型的类型信息

总结:

  • 泛型是将数据类型参数化,进行传递
  • 使用<T>表示当前类是一个泛型类
  • 泛型目前为止的优点:数据类型参数化,编译时自动进行类型检查和转换

2、泛型的上界

在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束

语法:

class 泛型类名称 {

         ...

}

示例:

//T 只接受 Number或Number的子类

class TestGeneric<T extends Number> {

}

//T 一定是 Number或者Number的子类
class TestGeneric<T extends Number> {}
public class Test2 {public static void main1(String[] args) {// Integer、Double等都是Number的子类TestGeneric<Number> testGeneric1 = new TestGeneric<>();TestGeneric<Integer> testGeneric2 = new TestGeneric<>();TestGeneric<Double> testGeneric3 = new TestGeneric<>();//TestGeneric<String> testGeneric4 = new TestGeneric<>(); // 编译错误}
}

1. 写一个泛型类 求一个数组中的最大值

发现报错了,因为 T 一定是引用数据类型,不能直接通过大于号小于号进行比较;T 最终被擦除为了Object 类型,而Object 类型没有实现Comparable接口,也不能通过compareTo进行比较。总结出 T 类型一定要是可以比较的

^

问题:怎么能够约束 这个T 一定是可以比较大小的?

答:T extends Comparable<T>,此时 T 一定是实现了 Comparable接口的

2. 写一个泛型方法

发现在调用的过程中没有指定参数类型。此时是通过类型推导来确定 T 的类型的

类型推导:根据实参传值 来推导 此时的类型

^

不使用类型推导的写法:

3. 静态泛型方法

不使用类型推导:

3、通配符

 ?  用于在泛型的使用,即为通配符

通配符解决什么问题?

上述程序会带来问题,如果现在泛型的类型设置的不是String,而是Integer

需要的解决方案:可以接收所有的泛型类型,但是又不能够让用户随意修改。这种情况就需要使用通配符 "?" 来处理

4、通配符上界

语法:

<? extends 上界>
<? extends Number>//可以传入的实参类型是Number或者Number的子类

示例:

此时无法在fun函数中对temp进行添加元素,因为temp接收的是Fruit和他的子类,此时存储的元素应该是哪个子 类无法确定。所以添加会报错!但是可以获取元素

通配符的上界,不能进行写入数据,只能进行读取数据。

5、通配符下界

语法:
<? super 下界>
<? super Integer> // 代表可以传入的实参的类型是Integer或者Integer的父类类型

示例:

通配符的下界,不能进行读取数据,只能写入数据

http://www.xdnf.cn/news/1140.html

相关文章:

  • Python 设计模式:享元模式
  • JVM虚拟机-类加载器、双亲委派模型、类装载的执行过程
  • 虚无隧穿产生宇宙(true nothing tunneling) 这个的真空是哪种
  • GitLab 提交权限校验脚本
  • 界面控件DevExpress WPF v25.1预览 - 支持Windows 11系统强调色
  • MuJoCo中的机器人状态获取
  • 第六篇:linux之解压缩、软件管理
  • Vue3集成sass
  • Unity 跳转资源商店,并打开特定应用
  • 滑动窗口学习
  • 【HTTPS协议原理】数据加密、如何防止中间人攻击、证书和签名、HTTPS完整工作流程
  • UnityDots学习(四)
  • 关于RPC
  • 图数据库nebula测试指南
  • 在 NVIDIA Orin (JetPack 6.0) 上安装 PyTorch 2.4 + Torchvision 0.19
  • 每日算法-250422
  • 几种Word转换PDF的常用方法
  • 如何在idea里创建注释模版
  • 真我推出首款 AI 翻译耳机,支持 32 种语言翻译
  • 拥抱健康生活,开启养生之旅
  • Android Jetpack Compose基础实践
  • iscsi服务端安装及配置
  • 【Python爬虫基础篇】--3.cookie和session
  • Office文档图片批量提取工具
  • 异构网络环境下的切换策略研究
  • 边缘计算全透视:架构、应用与未来图景
  • 基于Java+MySQL实现(Web)企业仓库存储管理系统
  • 金融数据分析(Python)个人学习笔记(12):网络爬虫
  • 【产品经理从0到1】用户研究和需求分析
  • 从项目真实场景中理解二分算法的细节(附图解和模板)