别再让类型限制你的代码!【Java包装类+泛型】,让数据结构开发一步到位

别再让类型限制你的代码!【Java包装类+泛型】,让数据结构开发一步到位
在这里插入图片描述
🎁个人主页:User_芊芊君子
🎉欢迎大家点赞👍评论📝收藏⭐文章
🔍系列专栏:Java.数据结构
在这里插入图片描述


在这里插入图片描述


【前言】

在Java中,包装类为基本数据类型提供对象封装,实现基本类型与对象的无缝转换;泛型则通过类型参数化,实现代码的通用复用并在编译期保证类型安全。二者结合,让数据结构能灵活适配多种类型,同时兼顾安全性与开发效率,是Java实现高效、通用数据操作的核心技术组合。

文章目录:

一、包装类

1. 什么是包装类?

包装类是Java中为8种基本数据类型提供的对应的类类型。它们位于java.lang包中,主要目的是将基本类型"包装"成对象,以便解决某些特殊场景。包装类实现了基本数据类型与对象之间的转换机制。

2.基本数据类型与包装类对应表

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

3.装箱和拆箱

装箱:将基本类型转换为包装类的过程拆箱:包装类转换为基本类型的过程
int i =10;Integer j =Integer.valueOf(i);//手动装箱int m = j.intValue();//手动拆箱
  • 自动装箱和自动拆箱
int a =10;Integer b = a;//自动装箱Integer c =(int)a;//自动装箱

【注意】
Integer 类型(默认范围:[-128~127])
超过范围就会新建对象
这时,a=200;b=200
如果打印a==b会返回false

publicstaticvoidmain(String[] args){Integer a =180;Integer b =180;System.out.println(a == b);}
在这里插入图片描述

二、泛型

1.什么是泛型?

泛型(Generics)是编程语言中一种强大的特性,一般的类和方法只能使用具体的类型,而泛型可以编写适用于多种数据类型的代码,而不需要为每种类型重复编写相似的代码。泛型的主要目的是提高代码的复用性、类型安全性以及代码的清晰度。

2.基本语法

class 泛型类名称<类型形参列表>{}classTest<T>{}

其他写法:

class 泛型类名称<类型形参列表>extends 继承类<这里可以使用类型参数>

3.引出泛型

实现一个类,该类中有一个可以存储任何类型数据的数组,并通过方法设置数组中的值,获取数组中的内容

publicclassArray{publicObject[] array =newObject[10];publicObjectgetPos(int pos){returnthis.array[pos];}publicvoidsetVal(int pos,Object val){this.array[pos]= val;}}
publicstaticvoidmain(String[] args){Array myArray =newArray(); myArray.setVal(0,10); myArray.setVal(1,"bba");String ret =(String) myArray.getPos(0);//强制类型转换System.out.println(ret);}
我们创建了一个Object类型的数组,可以存储任何类型的数据,因为Object是所有类型的父类,然后通过方法设置数组内容,但获取数据类型时会报错,发生了向下转型,这时要强制类型转换才能解决。这时,使用泛型则会更加便捷一点

使用泛型代码如下:

publicstaticvoidmain(String[] args){Array myArray =newArray(); myArray.setVal(0,10); myArray.setVal(1,"bba");//字符串也可以存放String ret =(String) myArray.getPos(0);//编译报错System.out.println(ret);}
publicstaticvoidmain(String[] args){Array<String>myArray =newArray<String>(); myArray.setVal(1,"bba");String ret = myArray.getPos(0);System.out.println(ret);}
< T >:就是占位符,表示当前类是一个泛型类;
类型后的< Integer >指定当前类型,后面就不需要强制类型转换

4.泛型的使用

泛型类<类型实参>变量名;//定义一个泛型类引用new 泛型类<类型实参>(构造方法实参);//实例化一个泛型类对象 eg:Array<Integer> list =newArray<Integer>();
后面的new< >里面的包装类可以不写,编译器会根据前面的包装类自动推导

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

5.擦除机制

泛型是编译时期的机制,代码运行时没有泛型这个概念
擦除机制:

在编译时,Java编译器会将泛型类型信息从代码中移除,这个过程就叫做类型擦除。擦除后,泛型类型会被替换为其边界类型(通常是Object)或者指定的类型。在必要的地方插入类型转换来保证类型安全生成桥接方式以保持多态性

上面的代码擦除后:

classMyArray{publicObject[] array =newObject[10];publicObjectgetPos(int pos){returnthis.array[pos];}}publicvoidsetVal(int pos,Object val){this.array[pos]= val;}

5.泛型的上界

5.1语法

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

eg1:

publicclassArray<EextendsNumber>{...}

E 要么是Number的子类,要么是Number自己
eg2:

publicclassMyArray<EextendsComparable<E>>{...}

E必须是实现了Comparable接⼝

5.2 示例

写一个泛型类,有一个方法,求T类型数组中最大值,数组没有指定类型

T类型是引用类型不能通过><==比较T类型擦除成Object,没有Comparable接口,所有要限定一下,给它一个上界
publicclassAlg<TextendsComparable<T>>{//T类型擦除成Object,没有Conmarable接口,所有要限定一下,给它一个上界publicTfindMaxVal(T[] array){T max = array[0];for(int i =0; i < array.length; i++){if(array[i].compareTo(max)>0){//T类型是引用类型不能通过><==比较 max = array[i];}}return max;}}
publicstaticvoidmain(String[] args){Alg<Integer> alg =newAlg<>();Integer[] array ={5,88,9,6,56,4};int ret = alg.findMaxVal(array);System.out.println(ret);}

6.泛型方法

6.1语法

 ⽅法限定符 <类型形参列表> 返回值类型⽅法名称(形参列表){...}

6.2 示例

泛型方法可以是static ,也可以不是static

静态方法不需要实例化引用对象,可直接调用,但参数没办法传入,so:static后面写
classAlg2{publicstatic<TextendsComparable<T>>TfindMaxVal(T[] array){T max = array[0];for(int i =0; i < array.length; i++){if(array[i].compareTo(max)>0){//T类型是引用类型不能通过><==比较 max = array[i];}}return max;}}
publicstaticvoidmain(String[] args){Integer[] array ={5,88,9,6,56,4};int ret =Alg2.findMaxVal(array);System.out.println(ret);}

7.通配符

? ⽤于在泛型的使⽤,即为通配符,用于表示未知类型

? extends 类:设置通配符上限 ,表示类型必须是T或其子类
? super 类:设置通配符下限,表示类型必须是T或其父类

【总结】

通过以上对Java包装类和泛型的详细介绍,我们可以看到它们在Java编程中的重要性和广泛应用。掌握好这两个知识点,对于编写高效、安全、可复用的Java代码具有重要意义。

Read more

Microsoft Edge WebView2 Runtime(运行库)快速部署 + 调试指南(精简实用、适配开发 + 用户双场景)

Microsoft Edge WebView2 Runtime(运行库)快速部署 + 调试指南(精简实用、适配开发 + 用户双场景)

WebView2运行库 v143.0.3650.139 x64 精简安装(下载) 一、WebView2 Runtime 快速安装部署(用户 / 开发通用,必做) ✅ 1. 系统预装情况 ▸ Windows 11 系统 默认自带 常青版 WebView2 运行库,无需手动安装;▸ Windows 10/7/8.1 需手动安装,缺失则调用 WebView2 控件的软件会弹窗报错「缺少 WebView2 运行环境」。 ✅ 2. 两种官方安装方式(推荐) 方式 1:常青版(Evergreen Runtime)- 首选 ▸ 特点:体积小(引导包仅

By Ne0inhk

Flutter 三方库 xpath_selector 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、透明、精准的 HTML/XML 数据抓取与 Web 结构解析引擎

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 xpath_selector 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、透明、精准的 HTML/XML 数据抓取与 Web 结构解析引擎 在鸿蒙(OpenHarmony)系统的网络爬虫、自动化测试审计、或者是从复杂的第三方 Web 公告(HTML)中提取关键数据(如新闻标题、资产负债表)时,如何摆脱凌乱的正向正则(Regex),转而使用业界标准的 XPath 语法进行语义化选取?xpath_selector 为开发者提供了一套工业级的、基于 Dart 的 HTML/XML 结构化查询方案。本文将深入实战其在鸿蒙端数据治理中的应用。 前言 什么是 XPath Selector?

By Ne0inhk

Java 算法实践(七):动态规划

这回溯算法本质上是一种暴力的穷举搜索,它遍历了问题的所有可能性(状态空间树)。然而,在许多问题中,回溯搜索会产生大量的重叠子问题,导致计算资源的极度浪费。 动态规划(Dynamic Programming, DP) 动态规划并非一种具体的算法,而是一种数学优化的思维方式。是一种通过将复杂问题分解为子问题,并存储子问题的解以避免重复计算的算法技术。它与分治法(Divide and Conquer)的区别在于:分治法的子问题通常是独立的(如归并排序),而动态规划的子问题是重叠的。 DP 的核心思想是空间换时间。通过维护一个表格(Table,通常是数组)来记录已经计算过的状态,将指数级的时间复杂度优化为多项式级(通常是线性或平方级)。 一、 从递归到动态规划:思维演进 理解 DP 的最佳路径是从斐波那契数列(Fibonacci)开始。虽然这是一个简单的数学问题,但它完美展示了算法复杂度的演变。 1.1 暴力递归 斐波那契数列定义: f ( n ) = f ( n − 1

By Ne0inhk
【数据结构入坑指南(三.1)】--《面试必看:单链表与顺序表之争,读懂“不连续”之美背后的算法思想》

【数据结构入坑指南(三.1)】--《面试必看:单链表与顺序表之争,读懂“不连续”之美背后的算法思想》

🔥@晨非辰Tong:个人主页  👀专栏:《C语言》、《数据结构与算法》 💪学习阶段:C语言、数据结构与算法初学者 ⏳“人理解迭代,神理解递归。” 引言:学完顺序表,深受其扩容和插入删除低效之苦? 是时候认识单链表了。它用指针串联数据,以“不连续”的物理结构,完美解决了顺序表的痛点。 接下来,让我们一起探索这种更优雅的数据结构。 目录 一、单链表特性全解 1.1  单链表:数据的"一线牵" 1.2  单链表结构:数据的“小火车” 二、单链表的实现(初) 2.1  铺垫 2.2  单链表尾插 2.3  单链表头插 2.4

By Ne0inhk