【数据结构】_包装类与泛型

目录

1. 包装类

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

1.2 (自动)装箱和(自动)拆箱

1.2.1 装箱与拆箱

1.2.2 自动(显式)装箱与自动(显式)拆箱

1.3 valueOf()方法

2. 泛型类

2.1 泛型类与Object类

2.2 泛型类语法

2.3 泛型类示例

2.4 裸类型(Raw Type)

2.5 泛型类的编译

2.5.1 擦除机制

2.5.2 泛型类型数组的实例化

2.6 泛型的上界

2.6.1  N为接口

 2.6.2   Number为类

3. 泛型方法

3.1 语法

3.2 泛型方法示例

3.2.1 普通类的普通泛型方法

3.2.2 普通类的静态泛型方法


1. 包装类

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

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

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

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

1.2 (自动)装箱和(自动)拆箱

1.2.1 装箱与拆箱

装箱(装包):把基本数据类型变为对应的包装类型;

拆箱(拆包):把引用类型变为基本数据类型;

1.2.2 自动(显式)装箱与自动(显式)拆箱

代码示例1:自动装箱与显式装箱:

        int a = 10;// 自动装箱Integer val = a;System.out.println(val);// 显式装箱Integer val2 = Integer.valueOf(a);Integer val3 = new Integer(a);System.out.println(val2);System.out.println(val3);

 代码示例2:自动拆箱:

        Integer val1 = 10;// 自动拆箱int a = val1;System.out.println(a);// 显式拆箱// 拆为int类型int a2 = val1.intValue();System.out.println(a2);// 拆为double类型double a3 = val1.doubleValue();System.out.println(a3);

 注:(1)自动装箱的底层逻辑:Integer包装类的valueOf()方法: 

(2)自动拆箱的底层逻辑:Integer包装类的intValue()方法:

(3)显式拆箱时,Integer包装类不止提供了intValue()方法,还提供了doubleValue()等方法:

可以根据所需的基本类型对应调用其方法,在上文示例中,输出结果为:

1.3 valueOf()方法

试运行以下代码:

        Integer a = 127;Integer b = 127;System.out.println(a==b);Integer c = 128;Integer d = 128;System.out.println(c==d);

输出结果为:

原理注解:

(1)Integer包装类的valueOf方法源代码与方法内部相关量的值:

(2)方法含义:

如果i在[low, high]即[-128, 127]之间,则返回cache缓存数组中下标为i+128位置的元素:

如i=0时存储在cache[128],i=-128时则存储在cache[0],i=127时则存储在cache[255];

即在缓存数组中存储了256个数字;

在该范围内的i调用valueOf方法调用到的是同一个元素,故而a=b;

在该范围外的i调用valueOf方法会new Integer对象,作为引用类型,==判断的是引用类型是否是对一个对象,故而a!=b;

2. 泛型类

一般的类和方法只能使用具体的类型:基本类型或自定义类,泛型就是适用于多种类型,即对参数实现了参数化;

2.1 泛型类与Object类

现要求实现一个不限制元素种类的数组,联想到Object类,示例代码如下:

class MyArray{public Object[] obj = new Object[3];public Object getPos(int pos){return obj[pos];}public void setPos(int pos,Object val){obj[pos]=val;}
}
public class Demo1 {public static void main(String[] args) {MyArray myArray = new MyArray();myArray.setPos(0,10);myArray.setPos(1,"hello");myArray.setPos(2,10.0);double ret = myArray.getPos(2);System.out.println(ret);}
}

报错如下:

 如要创建double类型变量对数组元素进行接收,则需要进行强转:

double ret = (double)myArray.getPos(2);

上文设计的数组具有以下特点:

① 任何数据都可以存储; ② 获取数据时必须进行强制类型转换;

这并非我们需要实现的泛型数组,通常需要实现的泛型数组需求是:存储一种类型的数据;

泛型编程是将类型作为参数传递的编程方式,目的是指定当前容器后可以存放某一种类型的数据;

2.2 泛型类语法

// 泛型的一般使用方法
class 泛型类名称<类型形参列表>{
}
class ClassName<T1,T2...Tn>{
}// 泛型类的继承
class 泛型类名称<类型形参列表> extends 继承类{
}
class ClassName<T1,T2,...Tn> extends ParentClass<T1>{
}

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

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

E表示Element,K表示Key,V表示Value,N表示Number,T表示Type;

泛型当中不能实例化一个泛型类型的数组,如:

T[] ts = new T[5];

是错误的;

③ 泛型类实例化的同时会指定当前泛型类的指数参数类型,如果二者冲突,就会报错,

这也是泛型编程的一个意义所在:泛型编程在程序编译时,存储数据时自动进行类型检查; 

2.3 泛型类示例

class MyArray<T>{public T[] obj = (T[])new Object[3];public T getPos(int pos){return obj[pos];}public void setObj(int pos, T val){obj[pos]=val;}
}
public class Demo1 {public static void main(String[] args) {// 实例化对象的同时指定当前泛型类的指定参数类型// 指定参数的类型必须是引用类型,如int非法而Integer合法MyArray<Integer> myArray1 = new MyArray<Integer>();myArray1.setObj(0,10);myArray1.setObj(1,78);myArray1.setObj(2,66);double ret1= myArray1.getPos(1);System.out.println(ret1);System.out.println("-------------------");MyArray<String> myArray2 = new MyArray<String>();myArray2.setObj(0,"hello");myArray2.setObj(1,"world");myArray2.setObj(2,"java");String ret2 = myArray2.getPos(1);System.out.println(ret2);}
}

输出结果为:

2.4 裸类型(Raw Type)

裸类型是一个泛型类但没有带类型实参,例如:

class MyArray<T>{public T[] obj = (T[])new Object[3];public T getPos(int pos){return obj[pos];}public void setObj(int pos, T val){obj[pos]=val;}
}
public class Demo1 {public static void main(String[] args) {MyArray list = new MyArray();}
}

但请注意:裸类型是为了兼容老版本的API,在编程时请避免裸类型的使用;

2.5 泛型类的编译

2.5.1 擦除机制

class MyArray<T>{public T[] obj = (T[])new Object[3];public T getPos(int pos){return obj[pos];}public void setObj(int pos, T val){obj[pos]=val;}
}
public class Demo1 {public static void main(String[] args) {MyArray<Integer> myArray = new MyArray<Integer>();myArray.setObj(0,85);int ret = myArray.getPos(0);System.out.println(ret);}
}

查看上文代码的字节码文件:

在编译完成后,运行过程中是没有泛型的概念的,此时所有的T都被擦除为Object,通过上述的编译器生成的字节码文件中是不包含泛型的类型信息的;

2.5.2 泛型类型数组的实例化

java语法规定:在实例化数组时必须提供具体的元素类型,故而不能直接实例化泛型类型数组

方法1:(上文擦除机制部分示例代码的在泛型类中创建数组的方法):

class MyArray<E>{public E[] obj = (E[]) new Object[3];
}

但该种写法存在问题:试运行以下代码:

class MyArray<E>{public E[] obj = (E[]) new Object[3];public E getPos(int pos){return obj[pos];}public void setObj(int pos,E val){obj[pos]=val;}// 返回数组的方法public E[] getArray(){return obj;}
}
public class Demo1 {public static void main(String[] args) {MyArray<Integer> myArray = new MyArray<Integer>();myArray.setObj(0,10);myArray.setObj(1,85);Integer[] integers = myArray.getArray();}
}

报错及分析如下:

在继承与多态章节已经提到过,向下转型是不安全的;

java的数组实现非常特殊,

此处可以理解为:jvm认为使用一个固定类型如Integer或String等等类型的对象来接收Object类型对象是不安全的;

正确代码为:(使用反射)

class MyArray<E>{public E[] obj;public MyArray(Class<E>clazz, int capacity){// 参数为数组元素类型与容量obj = (E[])Array.newInstance(clazz, capacity);}public E getPos(int pos){return obj[pos];}public void setObj(int pos, E val){obj[pos]=val;}public E[] getArray(){return obj;}
}
public class Demo1 {public static void main(String[] args) {MyArray<Integer> myArray = new MyArray<>(Integer.class,10);myArray.setObj(0,1997);myArray.setObj(1,85);Integer[] integers = myArray.getArray();}
}

但以上方法并不常用,更推荐方法2:; 

继承与多态文章链接如下:

CSDN

方法2:参考java的ArrayList源码的get方法:

对于泛型类型数组的实例化,不能直接使用泛型类型作为数组元素的类型,故而可以使用Object类结合强制类型转换实现泛型类型数组的实例化:

class MyArray<E>{public Object[] obj = new Object[3];public E getPos(int pos){return (E)obj[pos];}public void setPos(int pos, Object val){obj[pos] = val;}
}

2.6 泛型的上界

2.6.1  <E extends N> N为接口

表示实例化对象时指定的参数类型一定已经实现了N接口;

// 写一个泛型类求一个数组的最大值
class Alg<E extends Comparable<E>>{public E findMax(E[] array){E max=array[0];for(int i=0;i<array.length;i++){if(max.compareTo(array[i])<0){max = array[i];}}return max;}
}
public class Demo2 {public static void main(String[] args) {Alg<Integer> alg = new Alg<Integer>();Integer[] array = {1,4,2,10,9,8,17,5};System.out.println("Array is:");for(Integer x:array){System.out.print(x+" ");}System.out.println();Integer val =  alg.findMax(array);System.out.println("The max element in the array is "+val);}
}

输出结果为:

   

 2.6.2  <E extends Number> Number为类

表示E是Number的子类或E就是Number本身;

参考Number (Java Platform SE 8 ) (oracle.com)

 Integer、Double、Long、Short等等都是Number常见的直接子类:

class A<E extends Number>{A<Number> a1 = new A<>();A<Integer> a2 = new A<>();A<Double> a3 = new A<>();// A<String> a4 = new A<>();
}

3. 泛型方法

3.1 语法

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

3.2 泛型方法示例

3.2.1 普通类的普通泛型方法

class Alg2{public<E extends Comparable> E findMax(E[] array){E max = array[0];for(int i=0;i<array.length;i++){if(max.compareTo(array[i])<1){max=array[i];}}return max;}
}
public class Demo4 {public static void main(String[] args) {Alg2 alg2 = new Alg2();Integer[] arr = {19,9,7,85,25};System.out.println("Array is: ");for(Integer x:arr){System.out.print(x+" ");}System.out.println();Integer val = alg2.<Integer>findMax(arr);System.out.println("The max element in the array is "+val);}
}

输出结果为:

 注:调用泛型方法时泛型类型可以省略:

 Integer val = alg2.<Integer>findMax(arr);

 上行代码可以简写为:

 Integer val = alg2.findMax(arr);

编译器会根据传递给泛型方法的参数arr的类型判断E的类型;

3.2.2 普通类的静态泛型方法

class Alg2{public static<E extends Comparable> E findMax(E[] array){E max = array[0];for(int i=0;i<array.length;i++){if(max.compareTo(array[i])<1){max=array[i];}}return max;}
}
public class Demo4 {public static void main(String[] args) {Integer[] arr2 = {19,9,7,85,25};System.out.println("Array is: ");for(Integer x:arr2){System.out.print(x+" ");}System.out.println();Integer val = Alg2.findMax(arr2);System.out.println("The max element in the array is "+val);}
}

输出结果为:

静态泛型方法不再依赖于类的对象存在,可以使用类名直接调用;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/508098.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MATLAB环境下基于图像处理的计算病理学图像分割(MATLAB R2021B)

人工智能是病理学诊断和研究的重要新兴方法&#xff0c;其不仅可用于病理形态数据分析&#xff0c;还可整合免疫组化、分子检测数据和临床信息&#xff0c;得出综合的病理诊断报告&#xff0c;为患者提供预后信息和精准的药物治疗指导。计算病理学是病理学与AI、计算机视觉等信…

Mistral AI 的大语言模型怎么样?

对用户来说&#xff0c;更多的选择没坏处&#xff1b;如果这个选择本身还很优质&#xff0c;那就更棒了。 对话 早上&#xff0c;我收到了 Mistral 发来的邮件&#xff0c;提示我拥有了访问 Le Chat 的权限。 我一时觉得很奇怪&#xff0c;什么是 Le Chat&#xff1f; 然后我才…

深度学习需要掌握哪些数学基础?

《深度学习的数学》这本书再合适不过了。作者罗纳德.T.纽塞尔&#xff08;Ronald T. Kneusel&#xff09;&#xff0c;拥有超过 20年的机器学习行业经验。 本书适合有一定深度学习基础、了解Python编程语言的读者阅读&#xff0c;也可作为用于拓展深度学习理论的参考书。 为什么…

STM32(8)NVIC编程

中断源由部分片上外设产生 在misc.h中找&#xff0c;杂项 配置NVIC GPIO和AFIO不能产生中断源&#xff0c;但能通过EXTI&#xff0c;由EXTI产生中断源 NVIC不需要开启时钟&#xff0c;因为NVIC模块位于内核内部&#xff0c;芯片一上电就能工作。 中断响应函数 中断向量表在启…

韦东山嵌入式Liunx入门驱动开发五

文章目录 一、驱动程序基石1-1 休眠与唤醒1-2 POLL机制1-3 异步通知(1) 异步通知程序解析(2) 异步通知机制内核代码详解 1-4 阻塞与非阻塞1-5 定时器(1) 内核函数(2) 定时器时间单位 1-6 中断下半部 tasklet 本人学习完韦老师的视频&#xff0c;因此来复习巩固&#xff0c;写以…

【HTML】HTML基础6.2(表格之合并单元格)

目录 合并单元格效果 与<> ​编辑 合并属性 使用方法 步骤总结 合并单元格效果 代码 <table align"center" border"2"><thead><tr><th>演员</th><th>成就</th><th>剧照</th></tr>&l…

二维码门楼牌管理系统技术服务:二维码技术深度解析

文章目录 前言一、二维码的清晰度与准确性二、二维码的规格与容错率三、二维码门楼牌管理系统的应用与优势 前言 随着科技的进步&#xff0c;二维码技术在我们的日常生活中扮演着越来越重要的角色。尤其在门楼牌管理系统中&#xff0c;二维码技术的应用更是为城市管理带来了革…

3D数字孪生

数字孪生&#xff08;Digital Twin&#xff09;是物理对象、流程或系统的虚拟复制品&#xff0c;用于监控、分析和优化现实世界的对应物。 这些数字孪生在制造、工程和城市规划等领域变得越来越重要&#xff0c;因为它们使我们能够在现实世界中实施改变之前模拟和测试不同的场景…

Learning from Unlabeled 3D Environments forVision-and-Language Navigation

这篇论文是关于高级指令的 摘要 在视觉和语言导航 (VLN) 中&#xff0c;实体代理需要按照自然语言指令在真实的 3D 环境中进行导航。现有 VLN 方法的一个主要瓶颈是缺乏足够的训练数据&#xff0c;导致对未见过的环境的泛化效果不理想。虽然 VLN 数据通常是手动收集的&#x…

Java集合-ArraysLIst集合

集合是“由若干个确定的元素锁构成的整体”&#xff0c;在程序中&#xff0c;一般代表保存若干个元素(数据)的某种容器类。在Java中&#xff0c;如果一个Java对象可以在内部持有(保存)若干其他Java对象&#xff0c;并对外提供访问接口&#xff0c;我们把这种Java对象的容器称为…

lv20 QT主窗口4

熟悉创建主窗口项目 1 QAction 2 主窗口 菜单栏&#xff1a;fileMenu menuBar()->addMenu(tr("&File")); 工具栏&#xff1a;fileToolBar addToolBar(tr("File")); 浮动窗&#xff1a;QDockWidget *dockWidget new QDockWidget(tr("Dock W…

Java 计算某年份二月的天数

一、实验任务 要求编写一个程序&#xff0c;从键盘输入年份&#xff0c;根据输入的年份计算这一年的2月有多少天。 二、实验内容 三、实验结果 四、实现逻辑和步骤 &#xff08;1&#xff09;使用scanner类实现程序使用键盘录入一个年份。 &#xff08;2&#xff09;使用if语…