Collection与数据结构 数据结构预备知识(二):包装类与泛型

1.包装类

在Java中,由于基本类型不是继承自Object,为了在泛型代码中可以支持基本类型,Java给每个基本类型都对应了一个包装类.可以把包装类理解为基本数据类型所对应的引用数据类型.

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

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

除了char和int,其他的都是把首字母大写即可.

1.2 装箱和拆箱

1.2.1 装箱与拆箱的操作

装箱,就是把基本类型转换为包装类型.
拆箱,就是把包装类型转化为基本类型.

public class Package {
    int i = 10;
    //手动装箱操作
    Integer ij = Integer.valueOf(i);
//    Integer iij = new Integer(i);   jdk17已弃用
    //手动拆箱操作
    int a = ij.intValue();
}

上面的valueOf方法为静态方法,所以通过类名来调用.而intValue方法为非静态方法,通过对象名来调用.

public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
public int intValue() {
        return value;
    }

既然拆装箱可以手动,当然也可以自动,下面实现自动装箱与自动拆箱

class Auto_Package{
    int a = 10;
    //自动装箱操作
    Integer b = a;
    Integer c = (Integer) a;
    //自动拆箱操作
    int d = b;
    int e = (int) c;
}

1.2.2 包装类的范围问题

下面代码输出什么,为什么?
[阿里巴巴面试题]

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);
}

第一个输出true,第二个输出false.原因是,包装类的数据有一定地限制范围.下面我们看源码:

public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);//超出范围之后就会new一个新的对象出来
    }
private static class IntegerCache {
        static final int low = -128;//范围的最小值为-128
        static final int high;
        static final Integer[] cache;
        static Integer[] archivedCache;

        static {
            // high value may be configured by property
            int h = 127;//定义h=127
            String integerCacheHighPropValue =
                VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    h = Math.max(parseInt(integerCacheHighPropValue), 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;//范围的最大值为127

由于128超出了if语句的条件限制,所以就会new一个新的对象出来,它们指向的是不同的引用,而 == 比较的就是两个对象的地址是否想相同,所以第二个返回false.

2.泛型

2.1 什么是泛型

一般的类和方法,只能使用具体的类型,要不是基础类型,要不是引用类型,要不是自定义类型,如果需要编写多种类型都可以应用的代码,这种编程方式就会特别刻板.
于是在jdk1.5中就引入了新的语法,就是泛型:通俗讲,就是适用于多种类型.从代码上讲,就是把类型作为一种参数来传递,实现的是类型的参数化.

2.2 引出泛型

实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值?我们现在通过已有的知识来实现.

class MyArray{
    public Object[] array = new Object[10];//通过object类实现存储任何类型元素
    public void setPos(int pos,Object val){
        this.array[pos] = val;//设置元素
    }
    public Object getPos(int pos){
        return array[pos];//获取元素
    }
}
public class Main {
    public static void main(String[] args) {
        MyArray myArray = new MyArray();
        myArray.setPos(1,2);
        myArray.setPos(2,"String");
        String str = (String) myArray.getPos(2);//Object类向下转型
        System.out.println(str);
    }
}    

上述的数组可以存放任何类型的数据,但是更多情况下,我们还是希望能够只有一种数据类型,所以,泛型的目的就是指定当前容器要持有什么类型的对象,让编译器做检查.此时就需要把类型作为参数传递.

2.3 语法

class className<T1,T2,T3....>{
//这里可以使用指定的参数类型
}

我们对上述代码进行改写:

class MyArray2<T>{
    public T[] array = (T[]) new Object[10];//这种创建数组的方法其实不太好,我们后面说为什么,1
    public void setPos(int pos,T val){
        this.array[pos] = val;
    }
    public T getPos(int pos){
        return array[pos];
    }
}
public class Main {
    public static void main(String[] args) {
        MyArray2<Integer> myArray2 = new MyArray2<>();//2
        myArray2.setPos(1,2);
        myArray2.setPos(2,3);
        myArray2.setPos(3,4);
        int i = myArray2.getPos(3);//3
        System.out.println(i);
        //myArray2.setPos(4,"String");//4
    }
}

代码解释:

  1. 类名后的 < T >代表占位符,表示当前类型是一个泛型.
    类型的指定一般用一个大写字母来表示,常见的有:
    E 表示 Element
    K 表示 Key
    V 表示 Value
    N 表示 Number
    T 表示 Type
    S, U, V 等等 - 第二、第三、第四个类型
  2. 注释1处不可以new泛型的数组,T[] t = new T[5]不正确.后面new对象的时候尖括号中可以不写内容,是因为编译器可以根据上下文推导出类型实参.
  3. 注释2处<Integer>指定了当前对象的类型.
  4. 注释3处,无需强转,自动拆包.
  5. 注释4处报错,传入的字符串类型和Integer类型呢不匹配.

2.4 泛型编译原理

泛型是如何编译的呢,它遵循的是擦除机制,就是把所有的T擦除为Object.
Java的泛型机机制是编译时实现的,生成的字节码文件之后并不存在泛型的这种概念.

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

class MyArray3<T>{
    public T[] ts = (T[]) new Object[5];
    public T getPos(int pos){
        return ts[pos];
    }
    public T[] getTs(){
        return ts;
    }
}
public class Main {
    public static void main(String[] args) {
        MyArray3<Integer> myArray3 = new MyArray3<>();
        Integer[] integers = myArray3.getTs();
    }
}

在这里插入图片描述
这里我们看到,出现了类型转换异常,是因为在返回数组的操作中,T被擦除为了Object,而Object数组中可以存放任何类型的元素,而要把Object类型的数组传给一个Integer数组,编译器认为是不安全的.所以会出现异常.

接下来,我们解释为什么强转为(T[])类型的数组是不妥当的,其实和上面的问题是一样的道理,都是在类型中出现了问题.
在这里插入图片描述
上述我们可以看到编译器给出了警告,意思就是你Object类型数组里的元素要往T去转(向下转型),不一定都可以转成功,比如在new这个类型的对象的时候,T给的是一个Integer类型,而Object类型中的元素若是有String类型,这时就强转不了.我们前面提到向下转型本来就不安全,所以向下转型一定要谨慎.

正确的做法如下:

class MyArray4<T>{
    public Object[] array = new Object[10];
    public T getPos(int pos){
        return (T)array[pos];//这里虽然会报警告,但是在创建这个类的对象的时候,就已经指定了
        //类型,所以在添加的时候就是添加的这个类型,所以这里的强转是安全的
    }
    public void setPos(int pos,T val){
        array[pos] = val;//这里给数组放入的数据类型和创建对象时指定的T的类型是一致的
    }
}

2.6 泛型的上界

在定义泛型类的时候,有时需要对传入的类型进行一定的约束

2.6.1 语法

public class MyArray<类型形参 extends 类型边界> {
	........
}

实例1:

public class MyArray<T extends Number> {//传入的类型必须继承自Number
	........
}

实例2:

public class MyArray<E extends Comparable<E>>{//传入的类型必须实现comparable接口,即可比较对象
	...
}

2.7 泛型方法

2.7.1 语法

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

下面结合泛型上界和泛型方法来举个例子

class Alg{
    public <E extends Comparable<E>> E findMaxVal(E[] array){
        E max = array[0];
        for (int i = 1; i < array.length; i++) {
            if (max.compareTo(array[i])>0){
                max = array[i];
            }
        }
        return max;
    }
}
public class Main {
    public static void main(String[] args) {
        Integer[] array = {1,2,3,4,5};
        Alg alg = new Alg();
        System.out.println(alg.findMaxVal(array));
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于springboot+vue的旅游网站

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

【wails】(10):研究go-llama.cpp项目,但是发现不支持最新的qwen大模型,可以运行llama-2-7b-chat

1&#xff0c;视频演示地址 2&#xff0c;项目地址go-llama.cpp 下载并进行编译&#xff1a; git clone --recurse-submodules https://github.com/go-skynet/go-llama.cpp cd go-llama.cpp make libbinding.a项目中还打了个补丁&#xff1a; 给 编译成功&#xff0c;虽然有…

C#新语法(持续更新)

文章目录 顶级语句全局using 指令Using资源管理文件范围的命名空间声明可空的引用类型记录(record)类型 顶级语句 C#9.0中直接在C#文件中直接编写入口方法的代码&#xff0c;不用类&#xff0c;不用Main。同一个项目中只能有一个文件具有顶级语句。顶级语句中可以直接使用await…

Mysql数据库深入理解

目录 一、什么是数据库 二、Mysql基本架构图 1.Mysql客户端/服务器架构 2.客户端与服务器的连接过程 3.服务器处理客户端请求 4.一条查询SQL执行顺序 4.1连接器 4.2查询缓存 4.3解析器 4.4执行器 4.4.1预处理阶段 4.4.2优化阶段 4.4.3执行阶段 5.一条记录如何存…

汇丰:当前的美股是泡沫吗?

汇丰认为&#xff0c;当前的风险资产并不构成泡沫&#xff0c;更类似于2017年的市场环境&#xff0c;风险资产有望继续稳步上升。 隔夜美股飙涨&#xff0c;标普创三个月最大周涨&#xff0c;纳指收盘创历史新高。结合去年以来的强劲表现&#xff0c;有观点认为由科技股支撑的…

网络安全笔记-day7,共享文件服务器

文件共享服务器 准备阶段 打开虚拟机win2003 创建文件 D:. —share   –down   |  test1.txt   |   —up     01xxx.txt     02xxx.txt 配置IP win2003 192.168.1.10 255.255.255.0 winxp 192.168.1.20 255.255.255.0 创建共享文件夹 创建共享&#xff1…

freeRTOS动态内存heap4源码分析

1 前言 随着功能安全的推广&#xff0c;动态内存分配在RTOS领域的用武之地将越来越小。但heap4毕竟是为RTOS量身打造&#xff0c;相对简单&#xff0c;作为堆内存管理的入门学习&#xff0c;仍是很不错的选择。 1.1 标准c库动态内存函数的弊端 对于标准C库的malloc和free函数&…

阿里云2核4G服务器优惠价格30元、165元和199元1年,轻量和ECS

阿里云2核4G服务器租用优惠价格&#xff0c;轻量2核4G服务器165元一年、u1服务器2核4G5M带宽199元一年、云服务器e实例30元3个月&#xff0c;活动链接 aliyunfuwuqi.com/go/aliyun 活动链接如下图&#xff1a; 阿里云2核4G服务器优惠价格 轻量应用服务器2核2G4M带宽、60GB高效…

安装mysql8.0.36遇到的问题没有developer default 选项问题

安装mysql8.0.36的话没有developer default选项&#xff0c;直接选择customer就好了&#xff0c;点击next之后通过点击左边Available Products里面的号和中间一列的右箭头添加要安装的产品&#xff0c;最后会剩下6个 安装完成后默认是启动了&#xff0c;并且在电脑注册表注册了…

零基础-MySQL数据库的基本操作

①MYSQL数据库基本操作-DDL 1.DDL的解释 DDL&#xff08;Data Definition Language&#xff09;&#xff0c;数据定义语言&#xff0c;包括以下内容&#xff1a; 对数据库的常用操作 对表结构的常用操作 修改表结构 2.对数据库的常用操作 功能SQL查看所有的数据库show d…

【leetcode热题】 二叉树的右视图

给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4]示例 2: 输入: [1,null,3] 输出: [1,3]示例 3: 输入: [] 输出: []解法一 题…

javase day10笔记

第十天课堂笔记 debug调试★★★ 步骤: 设置断点 - > 启动调试debug -> 单步运行 -> 观察参数 单步跳过f8: 向下执行语句,不进入方法内部单步跳入f7: 进入方法内部执行单步跳出shift f8: 跳出当前方法,到方法调用处跳转到光标所在的位置alt f9: 变量整合 变量 …

机器学习K-means算法

K-Means 算法&#xff08;K-Means算法、K-Means 中心值计算、K-Means 距离计算公式、K-Means 算法迭代步骤、K-Means算法实例&#xff09; 问题引入 给你如下两种图片&#xff0c;快读回答2个问题&#xff0c;问 图1 中有几类五谷杂粮&#xff1f;问 图2 中有几类五谷杂粮&…

AI大模型学习:理论基石、优化之道与应用革新

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

使用git+ssh访问github,避免下载资源失败

一、创建github账户之后&#xff0c;记住注册邮箱和账户名 我的邮箱&#xff1a;yuanyan23mails.ucas.ac.cn 账户名&#xff1a;thekingofjumpshoot 下边的相关位置需要用自己的邮箱和用户名替代 二、输入本地生成秘钥和公钥命令&#xff0c;并且生成公私钥对 ssh-keygen …

亚马逊云科技《生成式 AI 精英速成计划》

最近亚马逊云科技推出了「生成式AI精英速成计划」&#xff0c;获取包含&#xff1a;免费学习热门生成式AI课程、技能证书、人力主管的面试辅导、云计算国际认证、免费去往北美参加全球用户大会等&#xff5e; 针对开发者和企业非技术专业人士&#xff0c;了解如何使用大模型平台…

Spring Bean加载优先级

当我们使用 ConditionalOnMissingBean / ConditionalOnBean注解去给某个 bean 注入赋予条件时&#xff0c;那在条件判断时我们需要确保条件判断过程所需的环境已准备好。 举个例子 下面的代码中有两个配置类&#xff0c;涉及两个 Bean 的注入 配置类 ConfigA 需要注入一个 A…

Uibot6.0 (RPA财务机器人师资培训第3天 )财务招聘信息抓取机器人案例实战

训练网站&#xff1a;泓江科技 (lessonplan.cn)https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981(本博…

使用 VMWare 安装 Android-x86 系统(小白版)

文章目录 VMWare 介绍Android 系统介绍概述最终效果前置步骤开始安装 VMWare 介绍 VMware Workstation是VMware公司开发的一款桌面虚拟化软件。它允许用户在一台物理计算机上同时运行多个操作系统&#xff0c;每个操作系统都在自己的虚拟机中运行。这使得用户可以在同一台计算…

数据可视化-ECharts Html项目实战(5)

在之前的文章中&#xff0c;我们学习了如何设置滚动图例&#xff0c;工具箱设置和插入图片。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#xff0c;谢谢 数据可视化-ECharts…