Java:包装类简单认识泛型

一、包装类

  包装类指的是基本数据类型(如int、double等)对应的类类型,我们可以通过包装类直接调用里面的方法!

基本数据类型                      包装类
byte                             Byte
short                            Short
int                              Integer
long                             Long 
float                            Float
double                           Double
char                             Character
boolean                          Boolean

除了Integer和Character,其余基本数据类型的包装类都是其对应基本数据类型的首字母大写! 



二、装箱和拆箱

1、装箱:把一个基本类型转为包装类型

 //装箱
public class Test1 {public static void main(String[] args) {int a=0;Integer ii=Integer.valueOf(a);//显示装箱Integer ii2=a;//自动装箱(底层调用的也是valueOf方法)}
}

2、拆箱:把一个包装类型转换为基本类型 

//拆箱
public class Test1 {public static void main(String[] args) {Integer ii=10;//自动装箱int a=ii.intValue();//手动拆箱int aa=ii;//自动拆箱(底层调用的也是intValue方法)}
}


一个问题:下面程序运行的结果是什么?

//程序运行的结果是什么?
public class Test1 {public static void main(String[] args) {Integer a=100;Integer b=100;System.out.println(a==b);//true or falseInteger c=200;Integer d=200;System.out.println(c==d);//true or false}
}

按照一般的逻辑,这个程序的运行结果要么都为true,要么都为false,那我们来看看实际过程中的结果到底是什么?

为什么会出现这样的结果?

 让我们来分析一下这段代码:

 1、首先,Integer a=100涉及的是装箱操作!这是我们上面所学的,而且我们知道这个装箱属于自动装箱它的底层调用的是valueOf方法!

2、那么就需要进入Integer类中看看这个valueOf方法了!

如图:

这个方法是这样执行的,如果参数 i 的范围属于[IntegerCache.low,IntegerCache.high]之间,那么函数返回数组的一个元素!

否则新实例化一个Integer类!

问题的关键就在于这个范围:让我来告诉大家,这个范围就是  [-128,127],因此才会出现截然相反的结果!



三、什么是泛型

泛型:简单来说,就是适用于许多许多类型!从代码上讲,就是对类型实现了参数化,使类型变得像参数一样可以作为一个数组的元素!

如果听不懂看,也没有问题,这个描述有点过于抽象,让我们看看实例加深对这段话的理解!

举个例子:实现一个类,类中包含一个数组成员,使得数组可以存放任何类型的数据!也可以根据成员方法返回数组中的某个元素! 

因为Object是所有类的父类,任何子类都继承于Object类,因此使用Object类作为数组类型。

//实现MyArray类:这个类有一个数组成员myArray,可以存放任何类型的数据
class MyArray{//数组成员public Object[] myArray=new Object[10];//成员方法:可以给数组传入任何类型的参数(如int,double等)public void setValue(int pos,Object x){myArray[pos]=x;}//成员方法:可以获取数组中的元素public Object getValue(int pos){return myArray[pos];}
}public class Test1 {public static void main(String[] args) {MyArray myArray=new MyArray();//实例化一个MyArray类myArray.setValue(1,12);//给myArray[1]存入int类型的1myArray.setValue(2,"hello");//给myArray[2]存入String类的"hello"}
}

  接下来我们进行一个操作,获取数组中的"hello",并将其赋值给String类的str。

如图:

这样做的化需要强制类型转换,因为你getValue返回值的类型是Object类,你将其返回值赋值给String类时就需要将Object类强制转换为String类

如图:强制类型转换后,程序不会报错!

   但是这里就有一个问题了,这个类只能接收任何类型的数据,但是每次取出数据的时候,我们都需要强制类型转换操作,才可以获取该数组元素!如果这个数组存储了许许多多的数据时,我们怎么知道要取出的元素是什么类型的呢?

答:这个时候,我们就需要对这个代码进行修改了,同时使用泛型语法!



泛型语法:

以下对代码的修改如下:

对类的修改:

1、在MyArray类的后面添加<T>:   这个T表示这个类是一个泛型 

2、setValue方法的传入参数的数据类型修改为T

3、getValue方法的返回值类型改为T,同时进行强制类型转换!

使用该泛型类时的语句修改:

1、实例化该泛型类时,在类名后面添加<类型名>,这个类型名取决于你即将传入的数据类型,比如,你要传入int类型的数据,就填Integer,如果要传入字符串,就填写String

//对类的修改
class MyArray<T>{        //1、<T>:表示这是一个泛型类public Object[] myArray=new Object[10];public void setValue(int pos,T x){     //2、参数传入类型给为TmyArray[pos]=x;}public T getValue(int pos){//3、方法的返回值类型改为Treturn (T)myArray[pos];//返回值强制类型转换为T}
}//使用该泛型类时的语句修改
public class Test1 {public static void main(String[] args) {MyArray<Integer> myArray=new MyArray<Integer>();//1、<>里面填写类型名myArray.setValue(1,12);//此时无法给数组传入String类的数据,因为实例化MyArray时,指定了当前类型为整型myArray.setValue(2,"hello");//!!!这一句报错!}
}


  这里要强调的是,看到上面代码我注释的报错语句没?如图:

此时无法给该数组出传入字符串,因为在前面实例化的时候指定了当前类型为int

它的具体原理如图:

这里解释一下我们要给数组传入的类型是int类型,为什么<>不填写int ,而是Integer,这是因为此时的<>只能填写类型名,不能填写基本数据类型(int、double之类)!因此得使用其基本类型的包装类代替!

注意:实例化的时候:以下为例:

MyArray<Integer> myarray=new MyArray<Integer>();

也可简写为:

MyArray<Integer> myarray=new MyArray<>();

使用了泛型之后,当每次取出数据时,就不需要我们进行强制类型转换! 



 如图:  类名<T> 表示一个占位符,表示当前类是一个泛型类(并不是一定要填T)

了解:【规范】类型形参一般使用一个大写字母表示,常用的名称有:

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


四、泛型的上界

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

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

 举一个例子:


//它表示以后给MyArray传入的参数,要么是Number这个类,要么是Number的子类
class MyArray<E extends Number>{
//...
}MyArray<Integer>;//正常运行,因为Integer是Number的子类型
MyArray<String>;//编译错误,因为String不是Numberd的子类型


举另外一个相对复杂的例子:

//它表示E必须是实现了Comparable接口的
class MyArray<E extends Comparable<E>>{
//...
}

实例:实现一个泛型类,可以找出数组中的最大值

//定义一个泛型类,找到数组当中的最大值://这样做是为了限定边界,T一定是实现了Comparable接口的
class Alg<T extends Comparable<T>>{public T findMax(T[] array){T max=array[0];for(int i=0;i< array.length;i++){//此时的max是一个引用类型,引用类型之间无法直接比较,所以要使用compareTo方法if(array[i].compareTo(max)>0){max=array[i];}}return max;}}

 接着就可以根据需要,求出任意类型数组中的最大值:

public static void main(String[] args) {//比较Integer类型数组Alg<Integer> alg=new Alg<>();Integer[]  array={1,2,3,4};Integer num=alg.findMax(array);System.out.println(num);//比较字符串数组Alg<String> alg1=new Alg<>();String[] array1={"abc","bcd","def"};String str=alg1.findMax(array1);System.out.println(str);}

运行结果:



五、泛型方法

泛型方法:顾名思义,就是适用于任何类的方法!

那么该如何写一个泛型类呢?


//泛型方法格式:
方法限定符 <类型形参列表> 返回值类型 方法名称 (形参列表){}
class Alg2{//写一个泛型方法:找出数组中的最大值(任何类型的数组都适用)public <T extends Comparable<T>> T findMax(T[] array){T max =array[0];for (int i = 0; i < array.length; i++) {if (array[i].compareTo(max) > 0) {max = array[i];}}return max;}
}

 使用泛型方法找出数组中最大值:

public static void main(String[] args) {//比较Integer类型的数组Alg2 alg2=new Alg2();Integer[] array={1,2,4,5};Integer max=alg2.findMax(array);//注意!System.out.println(max);//比较String类型的数组String[] array1={"abc","bcd","def"};String str =alg2.findMax(array1);System.out.println(str);}

有些伙伴可能会疑问,前面教学泛型类的时候,好歹在实例化泛型类的时候使用<>传入了类型名称如 Alg<Integer> alg=new Alg<Integer>();)这样起码可以知道是你的T表示什么类型,但是使用泛型方法时却没有使用<>中传入类型名称。这是为什么?

答:其实是因为,上述代码语句:Integer max=alg2.findMax(array)已经可以推出T是Integer类型了。它类似于实例化泛型类时的语句:MyArray<Integer>   myarray=new MyArray<>();

如果非要传入类型的话,也可以写成Integer max=alg2.<Integer>findMax(array)

程序运行:

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

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

相关文章

Java 小题 1

Java 小题 1 单选题 以下关于构造方法的描述错误的是 。 A. 构造方法的返回类型只能是void型。 B. 构造方法是类的一种特殊方法&#xff0c;它的方法名必须与类名相同。 C. 构造方法的主要作用是完成对类的对象的初始化工作。 D. 一个类可以定义多个构造方法。 正确答案…

09 网络ARP请求,响应,ICMP协议

arp协议_arp请求_arp回应 ICMP包构造ping搜狐服务器参考 #include <stdio.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <linux/if_packet.h> #include <linux/if_ether.h> #include <string.h> #includ…

基于Springboot Vue医院管理系统+数据库脚本+文档(万字)

项目效果视频: 基于Springboot Vue医院管理系统 一、 项目介绍 角色&#xff1a;管理员、患者、医生 基于springboot vue实现的医院管理系统&#xff0c;有管理员、医生和患者三种角色。系统拥有丰富的功能&#xff0c;能够满足各类用户的需求&#xff0c;系统提供了登录和注册…

Leetcode_27移除元素_26删除有序数组中的重复项_80删除有序数组中的重复项 II_169多数元素

文章目录 一、移除元素1.1 题目描述1.2 思路 二、删除有序数组中的重复项三、删除有序数组中的重复项 II四、多数元素 一、移除元素 1.1 题目描述 给你一个数组 nums 和一个值 val&#xff0c;你需要原地移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 …

PVE如何在CT中挂载目录

pct set 100 -mp1 /pveDir,mp/ctDir "pct set" pve命令 "100" ct编号 "-mp1" 挂载点1&#xff08;-mp2挂载点2&#xff09; "/pveDir" pve上的路径 "/ctDir" ct上的路径 若出现无权限写数据&#xff0c;参考下面的博客&…

2024年华为OD机试真题-文件缓存系统-Java-OD统一考试(C卷)

题目描述: 请设计一个文件缓存系统,该文件缓存系统可以指定缓存的最大值(单位为字节)。 文件缓存系统有两种操作:存储文件(put)和读取文件(get) 操作命令为put fileName fileSize或者get fileName 存储文件是把文件放入文件缓存系统中;读取文件是从文件缓存系统中访问已存…

ARM IHI0069F GIC architecture specification (1)

CH1.1 关于通用中断控制器 (GIC) GICv3 架构设计用于与 Armv8-A 和 Armv8-R 兼容的处理元件、PE 一起运行。 通用中断控制器 (GIC) 架构定义&#xff1a; • 处理连接到GIC 的任何PE 的所有中断源的架构要求。 • 适用于单处理器或多处理器系统的通用中断控制器编程接口。 GIC …

Day20 代码随想录(1刷) 二叉树

目录 654. 最大二叉树 617. 合并二叉树 700. 二叉搜索树中的搜索 98. 验证二叉搜索树 654. 最大二叉树 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。递归地在最大值 左边 的 子数…

最长公共子序列、LCS算法模型

LCS问题就是给定两个序列A和B&#xff0c;求他们最长的公共子序列。 在求解时&#xff0c;我们会设dp[i][j]表示为A[1 ~ i]序列和B[1 ~ j]序列中&#xff08;不规定结尾&#xff09;的最长子序列的长度。 if(a[i]b[i]) dp[i][j]dp[i-1][j-1]1; else dp[i][j]max(dp[i-1][j],dp…

局部静态变量实现单例模式,线程安全(推荐使用)c++11

class Singleton{ public:~Singleton();static Singleton& getInstance(){static Singleton instance;return instance; } private:Singleton(); };原因是C 11标准中新增了一个特性叫Magic Static&#xff1a;如果变量在初始化时&#xff0c;并发线程同时进入到static声明语…

白话模电:4.耦合、差分、无源滤波、反馈(考研面试常问问题)

一、介绍一下三极管多级放大电路的三种耦合方式及其特点&#xff1f;耦合的目的是什么&#xff1f; 多级放大电路中各放大级之间的连接方式称为耦合方式。常见的耦合方式有三种&#xff1a;阻容耦合&#xff08;RC耦合&#xff09;、直接耦合和变压器耦合。 耦合的目的是将信号…

Dubbo的服务降级

Dubbo的服务降级是一种容错机制&#xff0c;用于在分布式系统中处理在异常或故障情况下保障系统的可用性和稳定性。服务降级的核心思想是当调用远程服务失败或超时时&#xff0c;不会让整个业务流程崩溃&#xff0c;而是通过提供备用方案来保持部分功能的正常运行。 在Dubbo中&…

华南地区日用品电商综合服务商「广州麦和」积极推进数字化,企企通助力企业SRM系统上线

近期&#xff0c;由企企通携手华南地区线上最大的居家清洁&个人护理行业的电子商务综合服务商之一麦和&#xff08;广州&#xff09;实业有限公司&#xff08;以下简称“广州麦和”&#xff09;打造的SRM采购供应链协同系统上线&#xff0c;推进数字化采购管理体系建设&…

Xilinx缓存使用说明和测试

Xilinx缓存使用说明和测试 1 BRAM说明2 FIFO说明3 实例测试3.1 代码3.2 仿真本文主要介绍Xilinx FPGA芯片中BRAM和FIFO的使用方法和测试结果,主要针对流接口进行仿真。 1 BRAM说明 BRAM是Xilinx芯片中重要的存储资源,其可配置为单端口RAM/ROM或者双端口RAM/ROM,本文以最复杂…

el-select 下拉框点击某一禁选选项 按Esc关闭弹窗 下拉框无法收起问题

下面请看详细内容 会出现下图情况 弹窗能正常关闭 但是下拉框选项面板仍然存在 解决思路1&#xff1a; 本来想的是监听dialog的Esc关闭事件 关闭时修改el-select-dropdown的css样式 将display none 这个没实现 解决思路2&#xff1a; 看官网发现有个失焦事件 他手动触发失…

大词汇量高质量3D物体生成需要解决哪些问题?如何解决?

作者:Vallee | 来源:计算机视觉工坊 在公众号「计算机视觉工坊」后台,回复「原论文」可获取论文pdf和代码链接 DiffTF: 基于Transformer的大词汇量3D扩散模型 大词汇量3D物体生成 最近基于扩散模型的3D生成方法大火,但如何生成大量类别且高质量的3D模型还没得到很好地解决…

SpringBoot+Vue项目跨域问题

一、前言 问题 当我们遇到请求后台接口遇到 Access-Control-Allow-Origin 时&#xff0c;那说明跨域了。 跨域 跨域是因为浏览器的同源策略所导致&#xff0c;同源策略&#xff08;Same origin policy&#xff09;是一种约定&#xff0c;它是浏览器最核心也最基本的安全功能…

手写DNS服务器测速程序(工具分享)

手写DNS服务器测速程序&#xff08;工具分享&#xff09; 目的特性下载地址使用方法Golang代码 目的 为路由器设置dns时往往不知道如何设置dns为最佳&#xff0c;网上搜的脚本都不好用&#xff0c;于是手写了这个程序。 特性 多DNS服务器并发测试每个DNS服务器测试多次测试取…

python中的__dict__

类的__dict__返回的是&#xff1a;类的静态函数、类函数、普通函数、全局变量以及一些内置的属性都是放在类的__dict__里的&#xff0c; 而实例化对象的&#xff1a;__dict__中存储了一些类中__init__的一些属性值。 import的py文件 __dict__返回的是&#xff1a;__init__的…

DARTS-: ROBUSTLY STEPPING OUT OF PERFORMANCE COLLAPSE WITHOUT INDICATORS

DARTS-&#xff1a;增加辅助跳跃连接&#xff0c;鲁棒走出搜索性能崩溃 论文链接&#xff1a;https://arxiv.org/abs/2009.01027 项目链接&#xff1a;GitHub - Meituan-AutoML/DARTS-: Code for “DARTS-: Robustly Stepping out of Performance Collapse Without Indicators…