[Java] 泛型

news2025/5/10 5:09:28

目录

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<>();//2
        myArray.setValue(0,10);
        myArray.setValue(1,12);
        int ret = myArray.getValue(1);//3
        System.out.println(ret);
        myArray.setValue(2,"abc");//4

        MyArray<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.coloradmin.cn/o/2340556.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spark–steaming

实验项目: 找出所有有效数据&#xff0c;要求电话号码为11位&#xff0c;但只要列中没有空值就算有效数据。 按地址分类&#xff0c;输出条数最多的前20个地址及其数据。 代码讲解&#xff1a; 导包和声明对象&#xff0c;设置Spark配置对象和SparkContext对象。 使用Spark S…

深度学习训练中的显存溢出问题分析与优化:以UNet图像去噪为例

最近在训练一个基于 Tiny-UNet 的图像去噪模型时&#xff0c;我遇到了经典但棘手的错误&#xff1a; RuntimeError: CUDA out of memory。本文记录了我如何从复现、分析&#xff0c;到逐步优化并成功解决该问题的全过程&#xff0c;希望对深度学习开发者有所借鉴。 训练数据&am…

如何修复WordPress中“您所关注的链接已过期”的错误

几乎每个管理WordPress网站的人都可能遇到过“您关注的链接已过期”的错误&#xff0c;尤其是在上传插件或者主题的时候。本文将详细解释该错误出现的原因以及如何修复&#xff0c;帮助您更好地管理WordPress网站。 为什么会出现“您关注的链接已过期”的错误 为了防止资源被滥…

从零开始搭建Django博客①--正式开始前的准备工作

本文主要在Ubuntu环境上搭建&#xff0c;为便于研究理解&#xff0c;采用SSH连接在虚拟机里的ubuntu-24.04.2-desktop系统搭建的可视化桌面&#xff0c;涉及一些文件操作部分便于通过桌面化进行理解&#xff0c;最后的目标是在本地搭建好系统后&#xff0c;迁移至云服务器并通过…

健身房管理系统(springboot+ssm+vue+mysql)含运行文档

健身房管理系统(springbootssmvuemysql)含运行文档 健身房管理系统是一个全面的解决方案&#xff0c;旨在帮助健身房高效管理其运营。系统提供多种功能模块&#xff0c;包括会员管理、员工管理、会员卡管理、教练信息管理、解聘管理、健身项目管理、指导项目管理、健身器材管理…

Java从入门到“放弃”(精通)之旅——继承与多态⑧

Java从入门到“放弃”&#xff08;精通&#xff09;之旅&#x1f680;——继承与多态⑧ 一、继承&#xff1a;代码复用的利器 1.1 为什么需要继承&#xff1f; 想象一下我们要描述狗和猫这两种动物。如果不使用继承&#xff0c;代码可能会是这样&#xff1a; // Dog.java pu…

DeepSeek开源引爆AI Agent革命:应用生态迎来“安卓时刻”

开源低成本&#xff1a;AI应用开发进入“全民时代” 2025年初&#xff0c;中国AI领域迎来里程碑事件——DeepSeek开源模型的横空出世&#xff0c;迅速在全球开发者社区掀起热潮。其R1和V3模型以超低API成本&#xff08;仅为GPT-4o的2%-10%&#xff09;和本地化部署能力&#x…

使用 LangChain + Higress + Elasticsearch 构建 RAG 应用

RAG&#xff08;Retrieval Augmented Generation&#xff0c;检索增强生成&#xff09; 是一种结合了信息检索与生成式大语言模型&#xff08;LLM&#xff09;的技术。它的核心思想是&#xff1a;在生成模型输出内容之前&#xff0c;先从外部知识库或数据源中检索相关信息&…

Self-Ask:LLM Agent架构的思考模式 | 智能体推理框架与工具调用实践

作为程序员&#xff0c;我们习惯将复杂问题分解为可管理的子任务&#xff0c;这正是递归和分治算法的核心思想。那么&#xff0c;如何让AI模型也具备这种结构化思考能力&#xff1f;本文深入剖析Self-Ask推理模式的工作原理、实现方法与最佳实践&#xff0c;帮助你构建具有清晰…

安装 vmtools

第2章 安装 vmtools 1.安装 vmtools 的准备工作 1&#xff09;现在查看是否安装了 gcc ​ 查看是否安装gcc 打开终端 输入 gcc - v 安装 gcc 链接&#xff1a;https://blog.csdn.net/qq_45316173/article/details/122018354?ops_request_misc&request_id&biz_id10…

【论文阅读20】-CNN-Attention-BiGRU-滑坡预测(2025-03)

这篇论文主要探讨了基于深度学习的滑坡位移预测模型&#xff0c;结合了MT-InSAR&#xff08;多时相合成孔径雷达干涉测量&#xff09;观测数据&#xff0c;提出了一种具有可解释性的滑坡位移预测方法。 [1] Zhou C, Ye M, Xia Z, et al. An interpretable attention-based deep…

滑动窗口学习

2090. 半径为 k 的子数组平均值 题目 问题分析 给定一个数组 nums 和一个整数 k&#xff0c;需要构建一个新的数组 avgs&#xff0c;其中 avgs[i] 表示以 nums[i] 为中心且半径为 k 的子数组的平均值。如果在 i 前或后不足 k 个元素&#xff0c;则 avgs[i] 的值为 -1。 思路…

# 基于PyTorch的食品图像分类系统:从训练到部署全流程指南

基于PyTorch的食品图像分类系统&#xff1a;从训练到部署全流程指南 本文将详细介绍如何使用PyTorch框架构建一个完整的食品图像分类系统&#xff0c;涵盖数据预处理、模型构建、训练优化以及模型保存与加载的全过程。 1. 系统概述 本系统实现了一个基于卷积神经网络(CNN)的…

v-html 显示富文本内容

返回数据格式&#xff1a; 只有图片名称 显示不出完整路径 解决方法&#xff1a;在接收数据后手动给img格式的拼接vite.config中的服务器地址 页面&#xff1a; <el-button click"">获取信息<el-button><!-- 弹出层 --> <el-dialog v-model&…

【数学建模】孤立森林算法:异常检测的高效利器

孤立森林算法&#xff1a;异常检测的高效利器 文章目录 孤立森林算法&#xff1a;异常检测的高效利器1 引言2 孤立森林算法原理2.1 核心思想2.2 算法流程步骤一&#xff1a;构建孤立树(iTree)步骤二&#xff1a;构建孤立森林(iForest)步骤三&#xff1a;计算异常分数 3 代码实现…

<项目代码>YOLO小船识别<目标检测>

项目代码下载链接 YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为一个回归问题&#xff0c;能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法&#xff08;如Faster R-CNN&#xff09;&#xff0…

Crawl4AI:打破数据孤岛,开启大语言模型的实时智能新时代

当大语言模型遇见数据饥渴症 在人工智能的竞技场上&#xff0c;大语言模型&#xff08;LLMs&#xff09;正以惊人的速度进化&#xff0c;但其认知能力的跃升始终面临一个根本性挑战——如何持续获取新鲜、结构化、高相关性的数据。传统数据供给方式如同输血式营养支持&#xff…

【Spring Boot】MyBatis多表查询的操作:注解和XML实现SQL语句

1.准备工作 1.1创建数据库 &#xff08;1&#xff09;创建数据库&#xff1a; CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;&#xff08;2&#xff09;使用数据库 -- 使⽤数据数据 USE mybatis_test;1.2 创建用户表和实体类 创建用户表 -- 创建表[⽤⼾表…

[Android]豆包爱学v4.5.0小学到研究生 题目Ai解析

拍照解析答案 【应用名称】豆包爱学 【应用版本】4.5.0 【软件大小】95mb 【适用平台】安卓 【应用简介】豆包爱学&#xff0c;一般又称河马爱学教育平台app,河马爱学。 关于学习&#xff0c;你可能也需要一个“豆包爱学”这样的AI伙伴&#xff0c;它将为你提供全方位的学习帮助…

Qt开发:软件崩溃时,如何生成dump文件

文章目录 一、程序崩溃时如何自动生成 Dump 文件二、支持多线程中的异常捕获三、在 DLL 中使用 Dump 捕获四、封装成可复用类五、MiniDumpWriteDump函数详解 一、程序崩溃时如何自动生成 Dump 文件 步骤一&#xff1a;包含必要的头文件 #include <Windows.h> #include …