Java 包装类初识泛型

 登神长阶 第六阶  包装类&初识泛型


目录

😀一.包装类

😄1.基本数据类型以及其对应的包装类

😂2.装箱和拆箱

😇2.1.装箱(Boxing)

😉2.2.拆箱(Unboxing)

🫠2.3.注意事项

🥰二.泛型

😍1. 泛型类和泛型接口

🤩2.泛型类的具体使用

😜三.泛型方法

🤗1. 声明泛型方法

🫡2. 调用泛型方法

😛3. 类型推断

🤨4. 泛型方法与泛型类的关系

😷5. 泛型方法的优势

🤤四.泛型类的具体编译

🥴1. 类型擦除(Type Erasure)

😵‍💫2. 桥接方法(Bridge Method)

🤠3. 示例

🧐五.泛型的上界

😎1. 声明上界

🥹2.使用上界的好处

😣3. 上界通配符

😤4.注意事项 

🤓六.总结与反思


😀一.包装类

定义

        在Java中,由于基本类型不是继承自Object,为了在泛型代码中可以支持基本类型,Java给每个基本类型都对应了一个包装类型。包装类用于将基本数据类型转换为对象。它们允许在对象上执行额外的操作,例如将基本数据类型作为参数传递给方法,或者在集合类中存储基本数据类型。 

😄1.基本数据类型以及其对应的包装类

基本数据类型包装类

byte

Byte
shortShort
intInterger
longLong
floatFloat
doubleDouble
char

Character

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

😂2.装箱和拆箱

在Java中,装箱(boxing)和拆箱(unboxing)是指将基本数据类型转换为对应的包装类对象,以及将包装类对象转换为基本数据类型的过程。在使用过程中,装箱和拆箱带来不少的代码量,所以为了减少开发者的负担,java 提供了自动机制

😇2.1.装箱(Boxing)

装箱是指将基本数据类型转换为对应的包装类对象。在Java中,这个过程是自动进行的,称为自动装箱(autoboxing)。例如,将int类型的值装箱为Integer对象:

int num = 10;
Integer wrappedNum = num; // 自动装箱

😉2.2.拆箱(Unboxing)

拆箱是指将包装类对象转换为对应的基本数据类型。同样,这个过程也是自动进行的,称为自动拆箱(unboxing)。例如,将Integer对象转换为int类型:

Integer wrappedNum = 10;
int num = wrappedNum; // 自动拆箱

🫠2.3.注意事项

  • 自动装箱和拆箱可以使基本数据类型与其对应的包装类对象之间转换更加方便。
  • 自动装箱和拆箱发生在编译时,编译器会自动插入相应的代码。
  • 在使用自动装箱和拆箱时,需要注意空指针异常(NullPointerException),因为如果包装类对象为null,拆箱操作可能会导致异常。

总的来说,装箱和拆箱提供了方便的方式来在基本数据类型和包装类对象之间进行转换,同时避免了手动进行类型转换的繁琐工作。

🥰二.泛型

        在Java中,泛型(Generics)是一种强大的特性,用于在编译时检查和确保程序的类型安全性。泛型允许类、接口和方法在定义时使用一个或多个类型参数,以便在实际使用时可以指定具体的类型。

💡 一般的类和方法,只能使用具体的类型: 要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。----- 来源《 Java 编程思想》对泛型的介绍。
        泛型是在JDK1.5 引入的新的语法,通俗讲,泛型: 就是适用于许多许多类型 。从代码上讲,就是对类型实现了参数化。

😍1. 泛型类和泛型接口

  • 可以通过在类名后面使用尖括号<>来声明泛型类。
  • 泛型类可以包含一个或多个类型参数,用于指定具体类型。
  • 泛型接口的定义与泛型类类似,可以在接口中定义泛型类型参数。

 语法

public class Box<T> {
    private T value;

    public Box(T value) {
        this.value = value;
    }

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

 举例

class MyArray<T> {
    public T[] array = (T[])new Object[10];//1
    public T getPos(int pos) {
        return this.array[pos];
    }
    public void setVal(int pos,T val) {
        this.array[pos] = val;
    }
}

public class TestDemo {
    public static void main(String[] args) {
        MyArray<Integer> myArray = new MyArray<>();//2
        myArray.setVal(0,10);
        myArray.setVal(1,12);
        int ret = myArray.getPos(1);//3
        System.out.println(ret);
        myArray.setVal(2,"bit");//4
    }
}
上述代码解释:
  1. 类名后的 <T> 代表占位符,表示当前类是一个泛型类
【规范】类型形参一般使用一个大写字母表示,常用的名称有:
  • E 表示 Element
  • K 表示 Key
  • V 表示 Value
  • N 表示 Number
  • T 表示 Type
  • S, U, V 等等 - 第二、第三、第四个类型
  2. 注释1 处,不能 new泛型类型的数组
        这是因为Java泛型是通过类型擦除实现的,在运行时并不知道泛型的具体类型,而数组在创建时需要明确知道元素的类型。因此,创建泛型数组会导致编译器产生警告或错误。
  3. 注释 2 处,类型后加入 <Integer> 指定当前类型
  4. 注释 3处,不需要进行强制类型转换
  5. 注释 4 处,代码编译报错,此时因为在注释 2 处指定类当前的类型,此时在注释 4处,编译器会在存放元素的时候帮助我们进行类型检查

🤩2.泛型类的具体使用

语法

泛型类<类型实参> 变量名; // 定义一个泛型类引用
new 泛型类<类型实参>(构造方法实参); // 实例化一个泛型类对象
示例
MyArray<Integer> list = new MyArray<Integer>();

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

类型推导 (Type Inference)
当编译器可以根据上下文推导出类型实参时,可以省略类型实参的填写
MyArray < Integer > list = new MyArray <> (); // 可以推导出实例化需要的类型实参为 Integer

😜三.泛型方法

泛型方法是在方法声明时带有类型参数的方法。它们可以独立于所属类进行参数化,并且可以在调用时指定具体类型。以下是关于泛型方法的详细描述:

🤗1. 声明泛型方法

  • 在方法声明时,在返回类型之前使用尖括号<>来声明类型参数。

泛型方法可以有一个或多个类型参数,这些参数在方法中可以被用作参数类型、返回类型或局部变量类型。

public <T> void printArray(T[] array) {
    for (T element : array) {
        System.out.println(element);
    }
}

🫡2. 调用泛型方法

  • 在调用泛型方法时,可以在方法名之前使用尖括号<>来指定具体的类型参数。
  • 编译器会根据指定的类型参数来进行类型检查和类型推断。
Integer[] intArray = {1, 2, 3, 4, 5};
String[] strArray = {"Hello", "World"};

printArray(intArray); // 调用泛型方法并传入整型数组
printArray(strArray); // 调用泛型方法并传入字符串数组

😛3. 类型推断

  • 在调用泛型方法时,如果可以通过上下文推断出类型参数,可以省略类型参数的显式指定。
  • 编译器会根据方法参数的类型来推断类型参数。
Integer[] intArray = {1, 2, 3, 4, 5};
printArray(intArray); // 编译器会推断类型参数为Integer

🤨4. 泛型方法与泛型类的关系

  • 泛型方法可以独立于所属类进行参数化,即使所属类不是泛型类也可以定义泛型方法。
  • 泛型方法可以在普通类、泛型类、接口中声明和调用。
public class Utils {
    public static <T> T getLastElement(T[] array) {
        return array[array.length - 1];
    }
}

Integer[] intArray = {1, 2, 3, 4, 5};
Integer lastElement = Utils.getLastElement(intArray);

😷5. 泛型方法的优势

  • 提高代码的重用性和灵活性。
  • 可以在方法级别实现类型安全。

总的来说,泛型方法是Java中一种强大的特性,它允许在方法级别使用泛型,提高了代码的可复用性和类型安全性。通过类型推断简化调用。

🤤四.泛型类的具体编译

泛型类在Java中的编译过程涉及到类型擦除和桥接方法等概念。

以下是泛型类的具体编译过程:

🥴1. 类型擦除(Type Erasure)

  • 在编译阶段,泛型信息会被擦除,即将泛型类中的类型参数擦除为它们的边界或Object类型。
  • 泛型类中的类型参数会被替换为对应的边界类型或Object类型。
  • 泛型类的实例化和操作都是基于擦除后的类型进行的。

😵‍💫2. 桥接方法(Bridge Method)

  • 当泛型类中包含泛型方法时,在编译生成字节码时,编译器会自动生成桥接方法来保证泛型方法的类型安全性。
  • 桥接方法是编译器为了兼容Java泛型擦除机制而生成的方法,用于确保泛型类或泛型接口的方法能够正确地调用。
  • 桥接方法会根据擦除后的方法签名生成一个桥接方法,以便正确调用泛型方法。

🤠3. 示例

假设有以下泛型类定义:

public class Box<T> {
    private T value;

    public Box(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }
}

在编译后,上述代码会被转换为类似如下的形式:

public class Box {
    private Object value;

    public Box(Object value) {
        this.value = value;
    }

    public Object getValue() { // 编译后的桥接方法
        return value;
    }
}

这样,在泛型类的编译过程中,会进行类型擦除和桥接方法生成等操作,以确保在运行时可以正确处理泛型类的实例化和操作。

有关泛型擦除机制的文章截介绍: Java泛型擦除机制之答疑解惑 - 知乎 (zhihu.com)

🧐五.泛型的上界

在Java的泛型中,上界(Upper Bound)是指限定泛型类型参数必须是某个类或其子类。通过使用上界,可以在泛型中指定类型参数的范围,从而提高类型安全性和灵活性。

😎1. 声明上界

  • 在使用泛型时,可以使用extends关键字声明上界。
  • 语法格式为<T extends ClassName>,表示泛型类型参数T必须是ClassName类或其子类。
    public class Box<T extends Number> {
        private T value;
    
        public Box(T value) {
            this.value = value;
        }
    
        public T getValue() {
            return value;
        }
    }
    

🥹2.使用上界的好处

  • 类型限制:通过上界,可以限制泛型类型参数的范围,只允许特定类型或其子类作为参数。
  • 类型安全:使用上界可以避免在泛型中处理不符合要求的类型,提高类型安全性。
  • 方法调用:可以在泛型类或方法中调用上界类的方法,保证对应的操作是支持的。

😣3. 上界通配符

  • 上界通配符也可以在方法参数中使用,用于接受指定上界类型的对象。
public void processList(List<? extends Number> list) {
    // 对于Number及其子类的列表进行处理
}

😤4.注意事项 

  • 上界是单继承的,只能指定一个类作为上界。
  • 如果需要多个上界,请考虑使用接口作为上界。
  • 超类或接口可以放在泛型类型参数的位置,以限定类型参数的范围。

通过使用上界,可以有效地约束泛型类型参数的范围,提高代码的可读性、可维护性,并确保类型安全性。通过使用上界,可以有效地约束泛型类型参数的范围,提高代码的可读性、可维护性,并确保类型安全性。

🤓六.总结与反思

💡失败固然痛苦,但更糟糕的是从未去尝试。——西奥多.罗斯福

学习Java中的泛型是一次深刻的体验。泛型不仅提升了代码的类型安全性,还增加了代码的灵活性和复用性。初次接触时,可能会感觉有些晦涩难懂,需要花费一些时间去理解其工作原理和特性。然而,通过持续的学习和实践,逐渐能够领悟到泛型所带来的价值。

泛型使得在编译时就能够检查和确保数据类型的匹配,避免了在运行时可能出现的类型转换错误,从而提高了代码的健壮性。同时,泛型也允许我们编写更加通用和抽象的代码,可以独立于具体类型来设计和实现方法或类。这种灵活性使得我们可以更轻松地编写可复用的代码,同时提高了代码的可维护性和可扩展性。

尽管初期可能会面临一些学习曲线和挑战,但是通过不断地学习和实践,逐渐能够理解泛型的工作原理,并能够熟练地运用于实际项目中。泛型所带来的类型安全性和代码重用性是非常宝贵的,它能够帮助我们编写更加清晰、健壮和可维护的代码,从而提高了开发效率和代码质量。

因此,学习泛型是Java编程中不可或缺的一步。通过持续学习和实践,我们能够更好地利用泛型这一强大工具,开发出高效、可靠的程序,迈向优秀的Java开发者之路。


🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀

以上,就是本期的全部内容啦,若有错误疏忽希望各位大佬及时指出💐

  制作不易,希望能对各位提供微小的帮助,可否留下你免费的赞呢🌸

 

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

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

相关文章

[计算机知识] 各种小问题思考

哈希算法以及哈希冲突 哈希算法&#xff1a;将任何长度的输入通过散列函数转换成固定长度的字符串 哈希冲突&#xff1a;不同的输入经过哈希函数处理后得到相同的哈希值 因为哈希函数的输出域是有限的 解决哈希冲突&#xff1a; 1. 开放寻址&#xff1a;产生哈希冲突后&…

C语言程序与设计——指针地址与main函数

指针变量 在C语言中&#xff0c;最重要的就是对于指针和地址的理解&#xff0c;因为C语言是更接近底层的编程语言&#xff0c;所以它可以允许开发者对内存操作&#xff0c;这也是区别于其它编程语言的一个重要特性。 如何对内存进行操作呢。我们知道在编程过程中&#xff0c;在…

续二叉搜索树递归玩法

文章目录 一、插入递归二、寻找递归&#xff08;非常简单&#xff0c;走流程就行&#xff09;三、插入递归&#xff08;理解起来比较麻烦&#xff09; 先赞后看&#xff0c;养成习惯&#xff01;&#xff01;&#xff01;^ _ ^<3 ❤️ ❤️ ❤️ 码字不易&#xff0c;大家的…

ruoyi-nbcio-plus基于vue3的flowable流程设计器主界面升级修改

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://122.227.135.243:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a…

瑞_Redis_商户查询缓存

文章目录 项目介绍1 短信登录2 商户查询缓存2.1 什么是缓存2.1.1 缓存的应用场景2.1.2 为什么要使用缓存2.1.3 Web应用中缓存的作用2.1.4 Web应用中缓存的成本 2.2 添加Redis缓存2.2.1 背景2.2.2 缓存模型和思路2.2.3 代码实现2.2.4 测试附&#xff1a;IDEA控制台输出自动换行设…

Railway免费部署Flowise AI工作流教程

&#x1f9d9;‍♂️ 诸位好&#xff0c;吾乃斜杠君&#xff0c;编程界之翘楚&#xff0c;代码之大师。算法如流水&#xff0c;逻辑如棋局。 &#x1f4dc; 吾之笔记&#xff0c;内含诸般技术之秘诀。吾欲以此笔记&#xff0c;传授编程之道&#xff0c;助汝解技术难题。 &#…

C++中的vector与C语言中的数组的区别

C中的vector和C语言中的数组在很多方面都有所不同&#xff0c;以下是它们之间的一些主要区别&#xff1a; 大小可变性&#xff1a; vector是C标准模板库&#xff08;STL&#xff09;提供的动态数组容器&#xff0c;它的大小可以动态增长或减少。这意味着你可以在运行时添加或删…

常见滤波算法(PythonC版本)

简介 受限于MCU自身的ADC外设缺陷&#xff0c;精度和稳定性通常较差&#xff0c;很多场景下需要用滤波算法进行补偿。滤波的主要目的是减少噪声与干扰对数据的影响&#xff0c;让数据更加接近真实值。 一阶低通滤波 一阶低通滤波是一种信号处理技术&#xff0c;用于去除信号中…

Verilog奇技淫巧(二)

1. Verilog系统函数及其作用总结 $time用来查看当前仿真时刻&#xff0c;返回一个64bit的整数来表示的当前仿真时刻&#xff1b; $ realtime和$time的作用相同&#xff0c;$realtime但是返回的时间数字是一个实型数&#xff1b; $readmemb&#xff0c;用来从文件中读取数据到…

从redux的基本概念渐进式理解redux/toolkit的用法

概念 Redux toolkit是帮助提高redux开发效率的一个库 React-redux 是将React和Redux toolkit绑定在一起的一个库 action 是一个对象,里面有一个type属性 action creator是一个函数,这个函数可以返回上面的action对象。 reducer 是一个函数,接受两个参数(initilastate, acti…

北京哪位医生治疗糖尿病比较好?

糖尿病是一种常见的慢性疾病&#xff0c;主要是由于胰岛素分泌不足或利用障碍导致的以高血糖为特征的代谢性疾病。持续的高血糖和长期的代谢紊乱可能导致全身组织器官&#xff0c;特别是眼、肾、心血管及神经系统的损害和功能障碍。 北京崇文门医院朱学敏主任在糖尿病领域有有着…

LLM端侧部署系列 | 如何将阿里千问大模型Qwen部署到手机上?实战演示(下篇)

引言 简介 编译Android可用的模型 转换权重 生成配置文件 模型编译 编译apk 修改配置文件 绑定android library 配置gradle 编译apk 手机上运行 安装 APK 植入模型 效果实测 0. 引言 清明时节雨纷纷&#xff0c;路上行人欲断魂。 小伙伴们好&#xff0c;我是《小…

Matlab有限元编程案例全家桶【源码+理论文本】

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

制作一个RISC-V的操作系统九-上下文切换和协作式多任务(任务 任务上下文 多任务 多任务系统分类 协作式多任务 代码实现 )

文章目录 任务任务上下文多任务多任务系统分类协作式多任务代码实现asm volatile("csrw mscratch, %0" : : "r" (x));lw和swp tp 和 zero寄存器 待实现 任务 理解为一个段要执行的指令 任务上下文 理解为执行该任务时对应的CPU的寄存器各个状态 多任务…

Java并发编程基础面试题详细总结

1. 什么是线程和进程? 1.1 何为进程? 进程是程序的一次执行过程&#xff0c;是系统运行程序的基本单位&#xff0c;因此进程是动态的。系统运行一个程序即是一个进程从创建&#xff0c;运行到消亡的过程。 在 Java 中&#xff0c;当我们启动 main 函数时其实就是启动了一个…

【重学C语言】四、运算符和表达式

【重学C语言】四、运算符和表达式 概念左值与右值运算符一元运算符二元运算符三元运算符 优先级结合性 基本运算符赋值运算符算术运算符复合赋值运算符位运算符应用条件和逻辑运算符条件运算符逻辑运算符逻辑短路逻辑与&#xff08;&&&#xff09;的短路行为逻辑或&…

git版本控制工具

一、git工具介绍 1. 版本控制的概念与分类 版本控制是一种管理文件变更的技术&#xff0c;允许开发者记录文件或一组文件随时间的变化&#xff0c;以便能够恢复到先前的状态、查看历史更改、对比不同版本之间的差异&#xff0c;以及协同工作。版本控制系统主要有两种分…

jsp中使用session实现一个简单的购物车案例

1、需求分析 相信大家都有网上购物的经历&#xff0c;当用户选定某件商品时&#xff0c;只要选择“购买”&#xff0c;便可将商品添加到购物车中&#xff0c;购物车中包含了用户所有要购买的商品。接下来&#xff0c;以购买图书为例&#xff0c;使用Session模拟实现购物车功能…

vscode开发ESP32问题记录

vscode 开发ESP32问题记录 1. 解决vscode中的波浪线警告 1. 解决vscode中的波浪线警告 参考链接&#xff1a;https://blog.csdn.net/fucingman/article/details/134404485 首先可以通过vscode 中的IDF插件生成模板工程&#xff0c;这样会自动创建.vscode文件夹中的一些json配…

illustrator编组后透明图形也能挡住后面的图形的物体

今日学习使用illustrator&#xff0c;使用3D中的突出和斜角生成了一个圆柱体之后&#xff0c;扩展图形&#xff0c;修改之后发现一个奇怪的问题&#xff0c;编组中的透明物体挡住了后面的图形&#xff08;后面的图形是有颜色的&#xff09; 后面发现&#xff0c;原来是扩展生成…