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

Java 包装类简单认识泛型

学习目标:

1,以 能阅读Java集合源码 为目标 学习泛型

2,了解包装类

3,了解泛型

一,包装类

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

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

举个例子来说明两者的关系

比如说基本数据类型 byte  可以定义变量 a = 10, 而它的包装类  Byte 不仅可以定义变量 a = 10,在Byte里还有许多方法可以使用,因为他是一个类

除了 Integer Character, 其余基本类型的包装类都是首字母大写。

2,装箱和拆箱:

装箱/装包:  自动装箱 显示装箱

拆箱/拆包:  自动拆箱 显示拆箱

什么是装箱:

基本数据类型 变为 包装类类型 的过程 叫做装箱

什么是拆箱:

包装类类型 变为 基本数据类型 的过程 叫做拆箱

1) 装箱

这个叫做自动装箱(隐式装箱)

这个叫做显示装箱

注意:无论是隐式还是显示装箱,底层都调用了valueOf方法

2) 拆箱

这个叫做自动拆箱(隐式拆箱)

这个叫做显示拆箱

3)小测试

这里有一段代码,猜一下输出的值是什么

是不是和你想的不太一样,为什么会这样?

我们想一下,这个过程是 装箱 对吧,那我们查看 装箱的源码 就得看 valueOf 的源码

这是valueOf的源码,可以看到,当变量的值在一个 范围 里面的时候,他返回的值 是直接从数组里拿的,当不在这个范围里的时候,直接返回一个 新的值,把新的值和旧值比较,结果必然不一样

那么,这个范围是什么呢?

从源码中看到,最小值是-128 最大值是127

因此在[-128 ~ 127]内的 256个数字 在进行 == 比较的时候都会输出 true

刚才说了在数组里取值,那这个数组是什么?

返回的这个数组,它的下标逻辑是    

也就是说,当 i = -128 的时候,这个数组的下标是 -128 + ( - ( - 128 ) ) = 0 当 i=127 的时候,数组的下标是127+128 = 255 

这个数组我们称为 缓存数组

明白了吧,那我们就不能在超出这个范围的时候 用我们正常的算术逻辑 去比较值了吗?当然不是,可以使用equals方法

二,泛型

一般的类和方法,只能使用具体的类型: 要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。----- 来源《Java编程思想》对泛型的介绍。

1,什么是泛型

泛型是在JDK1.5引入的新的语法.
通俗讲,泛型:就是适用于许多许多类型。从代码上讲,就是对类型实现了参数化。

2,泛型的引出

现在要实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值,如何用代码实现?
分析:
1. 我们以前学过的数组,只能存放指定类型的元素,例如:
int[] array = new int[10]; String[] strs = new String[10];
2. 所有类的父类,默认为Object类。数组是否可以创建为Object?这样数组里不就可以存放任何类型的数据了吗?

这样数组里就可以存放你想要的任何类型了

但是

现在代码太乱了,主方法里什么类型都要放.更多情况下,我们还是希望他只能够持有一种数据类型。而不是同时持有这么多类型。并且每次取数据,都要进行强转,很麻烦
所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译器去做检查。此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。

3,泛型的语法

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

代码1示例:

分析代码1:

类定义:

首先我们放置了一个<E>,这个其实可以看做一个占位符,目的就是告诉编译器这是一个泛型E 是类型参数,代表该类可以操作任意类型的对象(后续使用时指定具体类型,如 Integer )

成员变量:

public Object[] arr = new Object[10]; 声明了一个长度为 10 的 Object 数组 arr,用于存储数据。因为是 Object 类型数组,理论上可以存储任何类型的对象,但实际使用时会根据泛型参数做类型转换

方法setValue:

public void SetValue(int pos, E val) 方法用于向数组 arr 的指定位置 pos 存储值 val。参数 pos 是数组索引,val 是要存储的、类型为 E 的值直接将 val 赋值给 arr[pos]

方法getValue:

public E getValue(int pos) 方法用于从数组 arr 的指定位置 pos 获取值,并将其转换为泛型类型 E 后返回通过 (E)arr[pos] 做强制类型转换,把 Object 类型的数组元素转换为 E 类型

主方法main:

MyArray<Integer> myArray = new MyArray(); 创建 MyArray 类的对象 myArray指定泛型类型为 Integer,但这里使用了原始类型创建(没有完整指定泛型参数,编译器会有警告 ),更规范的写法是 new MyArray<Integer>() 。当然不写也不报错

myArray.SetValue(1, 10); 调用 SetValue 方法,向 myArray 数组的索引 1 的位置存储值 10(因为泛型类型是 Integer,所以实际存储的是 Integer 类型的对象 )

那我们想要安放别的数据类型的时候怎么办,看代码:

代码2示例:

4,泛型是如何进行编译的

在编译的过程当中,将所有的T替换为Object这种机制,我们称为:擦除机制。
Java的泛型机制是在编译级别实现的。编译器生成的字节码在运行期间并不包含泛型的类型信息

也就是说泛型是编译时期的一种机制,在运行的时候 没有泛型的概念

编译完成后, E 会被擦除为 Object

擦除机制是一个非常晦涩的机制,我们来简单认识一下就好

由于这里我没有重写 toString方法,因此这里会输出test类地址

(shujujiegou是我的包名,不用管)

发现了吗,无论是Integer类型还是String类型,都被擦掉了.

通俗讲,此时<>里的内容不参与类型的组成,类型就是MyArray这就是 擦除机制

5,泛型的上界

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

观察这个代码,和之前的代码有什么不同

这两处就是不同的地方

此时规定传入的参数是Number或者Number的子类,但是String不是Number的子类,所以报错

此时就指定了传入参数E的一个界限 而不是想传什么就传什么

语法:

像之前那种没有上界的,可以认为E extends Object

这是什么意思?

即 E必须是实现了Comparable接口的

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

相关文章:

  • 《深度解构:React与Redux构建复杂表单的底层逻辑与实践》
  • C#使用EPPlus读写Excel
  • ubuntu20.04交叉编译vlc3.0.21 x64 windows版本
  • 大模型落地:AI 技术重构工作与行业的底层逻辑
  • Pytest 全流程解析:执行机制与报告生成实战指南
  • java 插入式注解的打开方式!
  • MySQL,Redis重点面试题
  • SQL179 每个6/7级用户活跃情况
  • Spring Framework源码解析——BeanPostProcessor
  • 【学习嵌入式day-22-Linux软件编程-IO】
  • SpringBoot集成支付宝二维码支付接口详解
  • Python3.10 + Firecrawl 下载 Markdown 文档:构建高效通用文章爬虫
  • 不同FPGA开发板系统移植步骤
  • Chrome插件开发【Service Worker练手小项目】
  • 【LeetCode刷题集】--排序(三)
  • 【智能的起源】人类如何模仿,简单的“刺激-反应”机制 智能的核心不是记忆,而是发现规律并能迁移到新场景。 最原始的智能:没有思考,只有简单条件反射
  • Mamba 原理汇总2
  • AI(2)-神经网络(激活函数)
  • 支持小语种的在线客服系统,自动翻译双方语言,适合对接跨境海外客户
  • 数据结构-数组扩容
  • 开发指南130-实体类的主键生成策略
  • Apache ECharts 6 核心技术解密 – Vue3企业级可视化实战指南
  • 排错000
  • 基于 ZooKeeper 的分布式锁实现原理是什么?
  • windows上RabbitMQ 启动时报错:发生系统错误 1067。 进程意外终止。
  • 150V降压芯片DCDC150V100V80V降压12V5V1.5A车载仪表恒压驱动H6203L惠洋科技
  • git:分支
  • 提示词工程实战:用角色扮演让AI输出更专业、更精准的内容
  • 软件测评中HTTP 安全头的配置与测试规范
  • 数据变而界面僵:Vue/React/Angular渲染失效解析与修复指南