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

【Java 数据结构】包装类简单认识泛型

包装类&简单认识泛型

  • 1 包装类
    • 1.1 基本数据类型和对应的包装类
    • 1.2 装箱和拆箱
    • 1.3 自动装箱和自动拆箱
  • 2 什么是泛型
  • 3 引出泛型
    • 3.1 语法
  • 4 泛型类的使用
    • 4.1 语法
    • 4.2 示例
    • 4.3 类型推导(Type Inference)
  • 5 泛型如何编译的
    • 5.1 擦除机制
    • 5.2 为什么不能实例化泛型类型数组
  • 6 泛型的上界
    • 6.1 语法
    • 6.2 示例
    • 6.3 复杂示例

1 包装类

在Java中,由于基本类型不是继承自Object,为了在泛型代码中可以支持基本类型,Java给每个基本类型都对应了一个包装类型。

1.1 基本数据类型和对应的包装类

在这里插入图片描述

1.2 装箱和拆箱

int i = 10;
// 装箱操作,新建一个 Integer 类型对象,将 i 的值放入对象的某个属性中
Integer ii = Integer.valueOf(i);
Integer ij = new Integer(i);
// 拆箱操作,将 Integer 对象中的值取出,放到一个基本数据类型中
int j = ii.intValue();

1.3 自动装箱和自动拆箱

可以看到在使用过程中,装箱和拆箱带来不少的代码量,所以为了减少开发者的负担,java 提供了自动机制。

int i = 10;
Integer ii = i; // 自动装箱
Integer ij = (Integer)i; // 自动装箱
int j = ii; // 自动拆箱
int k = (int)ii; // 自动拆箱

【面试题】
下列代码输出什么,为什么?

public static void main(String[] args) {Integer a = 127;Integer b = 127;Integer c = 128;Integer d = 128;System.out.println(a == b);System.out.println(c == d);
}

2 什么是泛型

一般的类和方法,只能使用具体的类型: 要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。----- 来源《Java编程思想》对泛型的介绍。
泛型是在JDK1.5引入的新的语法,通俗讲,泛型:就是适用于许多许多类型。从代码上讲,就是对类型实现了参数化。

3 引出泛型

实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值?
思路:

  1. 我们以前学过的数组,只能存放指定类型的元素,例如:int[] array = new int[10]; String[] strs = new
    String[10];
  2. 所有类的父类,默认为Object类。数组是否可以创建为Object?

代码示例:

class MyArray {public Object[] array = new Object[10];public Object getPos(int pos) {return this.array[pos];}public void setVal(int pos,Object val) {this.array[pos] = val;}}public class TestDemo {public static void main(String[] args) {MyArray myArray = new MyArray();myArray.setVal(0,10);myArray.setVal(1,"hello");//字符串也可以存放String ret = myArray.getPos(1);//编译报错System.out.println(ret);}
}

问题:以上代码实现后 发现

  1. 任何类型数据都可以存放
  2. 1号下标本身就是字符串,但是确编译报错。必须进行强制类型转换

虽然在这种情况下,当前数组任何数据都可以存放,但是,更多情况下,我们还是希望他只能够持有一种数据类型。而不是同时持有这么多类型。所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译器去做检查。此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。

3.1 语法

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

class MyArray<T> {public T[] array = (T[])new Object[10];//1public T getPos(int pos) {return this.array[pos];}public void setVal(int pos,T val) {this.array[pos] = val;}}public class TestDemo {public static void main(String[] args) {MyArray<Integer> myArray = new MyArray<>();//2myArray.setVal(0,10);myArray.setVal(1,12);int ret = myArray.getPos(1);//3System.out.println(ret);myArray.setVal(2,"bit");//4}
}

代码解释:

  1. 类名后的 代表占位符,表示当前类是一个泛型类
    了解: 【规范】类型形参一般使用一个大写字母表示,常用的名称有:
  • E 表示 Element
  • K 表示 Key
  • V 表示 Value
  • N 表示 Number
  • T 表示 Type
  • S, U, V 等等 - 第二、第三、第四个类型
  1. 注释1处,不能new泛型类型的数组

T[] ts = new T[5];//是不对的

T[] array = (T[])new Object[10];是否就足够好,答案是未必的。这块问题一会儿介
绍。
3. 注释2处,类型后加入 指定当前类型
4. 注释3处,不需要进行强制类型转换
5. 注释4处,代码编译报错,此时因为在注释2处指定类当前的类型,此时在注释4处,编译器会在存放元素的时
候帮助我们进行类型检查。

4 泛型类的使用

4.1 语法

泛型类<类型实参> 变量名; // 定义一个泛型类引用
new 泛型类<类型实参>(构造方法实参); // 实例化一个泛型类对象

4.2 示例

MyArray list = new MyArray();
注意:泛型只能接受类,所有的基本数据类型必须使用包装类!

4.3 类型推导(Type Inference)

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

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

5 泛型如何编译的

5.1 擦除机制

那么,泛型到底是怎么编译的?这个问题,也是曾经的一个面试问题。泛型本质是一个非常难的语法,要理解好他还是需要一定的时间打磨。
在这里插入图片描述
在编译的过程当中,将所有的T替换为Object这种机制,我们称为:擦除机制
Java的泛型机制是在编译级别实现的。编译器生成的字节码在运行期间并不包含泛型的类型信息。

5.2 为什么不能实例化泛型类型数组

class MyArray<T> {public T[] array = (T[])new Object[10];public T getPos(int pos) {return this.array[pos];}public void setVal(int pos,T val) {this.array[pos] = val;}public T[] getArray() {return array}}public static void main(String[] args) {MyArray<Integer> myArray1 = new MyArray<>();Integer[] strings = myArray1.getArray();
}
/*
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
at TestDemo.main(TestDemo.java:31)
*/

原因:替换后的方法为:将Object[]分配给Integer[]引用,程序报错。

public Object[] getArray() {
return array;
}

通俗讲就是:返回的Object数组里面,可能存放的是任何的数据类型,可能是String,可能是Person,运行的时候,直接转给Integer类型的数组,编译器认为是不安全的

6 泛型的上界

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

6.1 语法

class 泛型类名称<类型形参 extends 类型边界> {

}

6.2 示例

public class MyArray {

}

只接受 Number 的子类型作为 E 的类型实参

MyArray l1; // 正常,因为 Integer 是 Number 的子类型
MyArray l2; // 编译错误,因为 String 不是 Number 的子类型

了解: 没有指定类型边界 E,可以视为 E extends Object

6.3 复杂示例

public class MyArray<E extends Comparable> {

}

E必须是实现了Comparable接口的

相关文章:

【Java 数据结构】包装类简单认识泛型

包装类&简单认识泛型 1 包装类1.1 基本数据类型和对应的包装类1.2 装箱和拆箱1.3 自动装箱和自动拆箱 2 什么是泛型3 引出泛型3.1 语法 4 泛型类的使用4.1 语法4.2 示例4.3 类型推导(Type Inference) 5 泛型如何编译的5.1 擦除机制5.2 为什么不能实例化泛型类型数组 6 泛型…...

第139期 做大还是做小-Oracle名称哪些事(20240125)

数据库管理139期 2024-01-25 第139期 做大还是做小-Oracle名称哪些事&#xff08;20240125&#xff09;1 问题2 排查3 扩展总结 第139期 做大还是做小-Oracle名称哪些事&#xff08;20240125&#xff09; 作者&#xff1a;胖头鱼的鱼缸&#xff08;尹海文&#xff09; Oracle A…...

驱动开发--多路复用-信号

一、多路复用 每个进程都有一个描述符数组&#xff0c;这个数组的下标为描述符&#xff0c; 描述符的分类&#xff1a; 文件描述符&#xff1a;设备文件、管道文件 socket描述符 1.1 应用层&#xff1a;三套接口select、poll、epoll select&#xff1a;位运算实现 监控的描…...

LeetCode 2859. 计算 K 置位下标对应元素的和【位操作】1000

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…...

composer安装hyperf后,nginx配置hyperf

背景 引入hyperf项目用作微服务&#xff0c;使用composer 安装hyperf后&#xff0c;对hyperf进行nginx配置。 配置步骤 因为hyperf监听的是端口&#xff0c;不像其他laravel、lumen直接指向文件即可。所有要监听端口号。 1 配置nginx server {listen 80;//http&#xff1a…...

Flink对接Kafka的topic数据消费offset设置参数

scan.startup.mode 是 Flink 中用于设置消费 Kafka topic 数据的起始 offset 的配置参数之一。 scan.startup.mode 可以设置为以下几种模式&#xff1a; earliest-offset&#xff1a;从最早的 offset 开始消费数据。latest-offset&#xff1a;从最新的 offset 开始消费数据。…...

TryHackMe-Umbrella

靶场介绍 Breach Umbrella Corp’s time-tracking server by exploiting misconfigurations around containerisation. 利用集装箱化的错误配置&#xff0c;破坏Umbrella公司的时间跟踪服务器。 Task 1 What is the DB password? 数据库的密码是多少&#xff1f; 端口扫描&am…...

Excel导出警告:文件格式和拓展名不匹配

原因描述&#xff1a; Content-Type 原因&#xff1a;Content-Type&#xff0c;即内容类型&#xff0c;一般是指网页中存在的Content-Type&#xff0c;用于定义网络文件的类型和网页的编码&#xff0c;决定文件接收方将以什么形式、什么编码读取这个文件&#xff0c;这就是经常…...

kafka集群和Filebeat+Kafka+ELK

一、Kafka 概述 1.1 为什么需要消息队列&#xff08;MQ&#xff09; 主要原因是由于在高并发环境下&#xff0c;同步请求来不及处理&#xff0c;请求往往会发生阻塞。比如大量的请求并发访问数据库&#xff0c;导致行锁表锁&#xff0c;最后请求线程会堆积过多&#xff0c;从…...

golang map真有那么随机吗?——map遍历研究

在随机选取map中元素时&#xff0c;本想用map遍历的方式来返回&#xff0c;但是却并没有通过测试。 那么难道map的遍历并不是那么的随机吗&#xff1f; 以下代码参考go1.18 hiter是map遍历的结构&#xff0c;主要记录了当前遍历的元素、开始位置等来完成整个遍历过程 // A ha…...

详细分析对比copliot和ChatGPT的差异

Copilot 和 ChatGPT 是两种不同的AI工具&#xff0c;分别在不同领域展现出了强大的功能和潜力&#xff1a; GitHub Copilot 定位与用途&#xff1a;GitHub Copilot 是由GitHub&#xff08;现为微软子公司&#xff09;和OpenAI合作开发的一款智能代码辅助工具。它主要集成于Visu…...

TENT:熵最小化的Fully Test-Time Adaption

摘要 在测试期间&#xff0c;模型必须自我调整以适应新的和不同的数据。在这种完全自适应测试时间的设置中&#xff0c;模型只有测试数据和它自己的参数。我们建议通过test entropy minimization (tent[1])来适应:我们通过其预测的熵来优化模型的置信度。我们的方法估计归一化…...

研发日记,Matlab/Simulink避坑指南(五)——CAN解包 DLC Bug

文章目录 前言 背景介绍 问题描述 分析排查 解决方案 总结 前言 见《研发日记&#xff0c;Matlab/Simulink避坑指南&#xff08;一&#xff09;——Data Store Memory模块执行时序Bug》 见《研发日记&#xff0c;Matlab/Simulink避坑指南(二)——非对称数据溢出Bug》 见《…...

机器人3D视觉引导半导体塑封上下料

半导体塑封上下料是封装工艺中的重要环节&#xff0c;直接影响到产品的质量和性能。而3D视觉引导技术的引入&#xff0c;使得这一过程更加高效、精准。它不仅提升了生产效率&#xff0c;减少了人工操作的误差&#xff0c;还为半导体封装技术的智能化升级奠定了坚实的基础。 传统…...

(十二)Head first design patterns代理模式(c++)

代理模式 代理模式&#xff1a;创建一个proxy对象&#xff0c;并为这个对象提供替身或者占位符以对这个对象进行控制。 典型例子&#xff1a;智能指针... 例子&#xff1a;比如说有一个talk接口&#xff0c;所有的people需要实现talk接口。但有些人有唱歌技能。不能在talk接…...

C++从零开始的打怪升级之路(day21)

这是关于一个普通双非本科大一学生的C的学习记录贴 在此前&#xff0c;我学了一点点C语言还有简单的数据结构&#xff0c;如果有小伙伴想和我一起学习的&#xff0c;可以私信我交流分享学习资料 那么开启正题 今天分享的是关于vector的题目 1.删除有序数组中的重复项 26. …...

《设计模式的艺术》笔记 - 观察者模式

介绍 观察者模式定义对象之间的一种一对多依赖关系&#xff0c;使得每当一个对象状态发生改变时&#xff0c;其相关依赖对象皆得到通知并被自动更新。 实现 myclass.h // // Created by yuwp on 2024/1/12. //#ifndef DESIGNPATTERNS_MYCLASS_H #define DESIGNPATTERNS_MYCLA…...

Java如何对OSS存储引擎的Bucket进行创建【OSS学习】

在前面学会了如何开通OSS&#xff0c;对OSS的一些基本操作&#xff0c;接下来记录一下如何通过Java代码通过SDK对OSS存储引擎里面的Bucket存储空间进行创建。 目录 1、先看看OSS&#xff1a; 2、代码编写&#xff1a; 3、运行效果&#xff1a; 1、先看看OSS&#xff1a; 此…...

ModuleNotFoundError: No module named ‘half_json‘

问题: ModuleNotFoundError: No module named ‘half_json’ 原因: 缺少jsonfixer包 解决方法: pip install jsonfixerjson修正包地址: https://github.com/half-pie/half-json...

深入探究 Android 内存泄漏检测原理及 LeakCanary 源码分析

深入探究 Android 内存泄漏检测原理及 LeakCanary 源码分析 一、什么是内存泄漏二、内存泄漏的常见原因三、我为什么要使用 LeakCanary四、LeakCanary介绍五、LeakCanary 的源码分析及其核心代码六、LeakCanary 使用示例 一、什么是内存泄漏 在基于 Java 的运行时中&#xff0…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

c++第七天 继承与派生2

这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分&#xff1a;派生类构造函数与析构函数 当创建一个派生类对象时&#xff0c;基类成员是如何初始化的&#xff1f; 1.当派生类对象创建的时候&#xff0c;基类成员的初始化顺序 …...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...