Java的自动装箱和自动拆箱

news2024/11/17 13:22:01

自动装箱和拆箱在Java开发中的应用与注意事项

在Java开发中,自动装箱(Autoboxing)和自动拆箱(Unboxing)是指基本数据类型与其对应的包装类之间的自动转换。这些特性可以使代码更加简洁和易读,但在实际项目中也带来了某些潜在的问题。本文将详细介绍自动装箱和拆箱的概念,并探讨在Spring Boot项目开发和Bean转换中的应用与注意事项。

自动装箱和拆箱的概念

自动装箱:Java编译器在需要时会自动将基本数据类型转换为对应的包装类。例如,将一个int赋值给Integer

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

自动拆箱:Java编译器在需要时会自动将包装类转换为对应的基本数据类型。例如,将一个Integer赋值给int

Integer boxedNum = 10;
int num = boxedNum; // 自动拆箱
实际项目中的注意事项
  1. 性能影响:频繁的自动装箱和拆箱操作会导致额外的对象创建,影响性能,特别是在循环中频繁使用时。

    for (int i = 0; i < 1000; i++) {
        Integer boxedInt = i; // 每次循环都会创建一个新的Integer对象
    }
    

    建议:在性能关键的代码中,尽量使用基本数据类型,避免频繁的自动装箱和拆箱。

  2. 空指针异常:在自动拆箱时,如果包装类对象为null,会导致NullPointerException

    Integer nullInteger = null;
    int value = nullInteger; // 这会抛出NullPointerException
    

    建议:在进行拆箱之前,始终检查包装类对象是否为null,或使用Optional类来处理可能的null值。

  3. 相等性比较:使用==比较包装类对象时,比较的是对象的引用,而不是值。

    Integer a = 128;
    Integer b = 128;
    System.out.println(a == b); // 输出false,因为128超出了-128到127的缓存范围
    

    建议:使用.equals()方法进行包装类对象的值比较。

  4. 整数缓存:Java会缓存一定范围内的整数值(通常是-128到127)。在这个范围内的装箱对象可能会被重用,而超出范围的值则不会。

    Integer x = 127;
    Integer y = 127;
    System.out.println(x == y); // 输出true,因为它们被缓存
    
    Integer m = 128;
    Integer n = 128;
    System.out.println(m == n); // 输出false,因为它们没有被缓存
    
  5. 集合中的自动装箱和拆箱:在集合(如ListSet)中频繁操作基本数据类型时,会频繁发生装箱和拆箱操作。

    List<Integer> list = new ArrayList<>();
    for (int i = 0; i < 1000; i++) {
        list.add(i); // 自动装箱
    }
    
Spring Boot中自动装箱和拆箱的应用

在Spring Boot应用程序中,前端传值和JSON解析过程中可能涉及到自动装箱和拆箱。以下是具体示例:

前端传值到后端

假设前端发送一个包含整数的JSON对象:

{
  "age": 25
}

后端控制器方法:

@RestController
public class UserController {
    @PostMapping("/user")
    public ResponseEntity<String> createUser(@RequestBody User user) {
        // 处理逻辑
        return ResponseEntity.ok("User created");
    }
}

public class User {
    private Integer age;
    // getters and setters
}

在这个例子中,age字段是Integer类型,Spring Boot会自动将JSON中的整数值装箱为Integer对象。

JSON解析

假设以下JSON:

{
  "id": 123,
  "name": "John Doe"
}

对应的Java类:

public class Person {
    private Long id;
    private String name;
    // getters and setters
}

Jackson在解析JSON时,会将id字段的整数值(基本类型long)装箱为Long对象并赋值给Person类的id字段。同样地,如果我们从对象转换回JSON字符串,也可能涉及拆箱操作。

注意事项

  • Null处理:确保包装类字段不为null,避免在拆箱时引发NullPointerException
  • 性能考虑:在高并发和大数据量场景中,注意装箱和拆箱操作的性能影响。
  • 数据类型一致性:确保前端传递的数据类型与后端Java对象的字段类型一致。
Bean转换中的自动装箱和拆箱

在Bean转换过程中,如果两个Bean的相应属性类型不同,也会涉及到自动装箱和拆箱。以下是一个示例:

定义Bean

public class SourceBean {
    private int age;
    private boolean active;
    // getters and setters
}

public class TargetBean {
    private Integer age;
    private Boolean active;
    // getters and setters
}

使用Spring BeanUtils进行转换

public class BeanConversionExample {
    public static void main(String[] args) {
        SourceBean source = new SourceBean();
        source.setAge(25);
        source.setActive(true);

        TargetBean target = new TargetBean();
        org.springframework.beans.BeanUtils.copyProperties(source, target);

        System.out.println("Age: " + target.getAge()); // 自动装箱
        System.out.println("Active: " + target.getActive()); // 自动装箱
    }
}

注意事项

  1. 空值处理:当目标Bean的属性是基本数据类型时,源Bean的相应属性如果是null,需要小心处理,因为自动拆箱null会导致NullPointerException

    public class SourceBean {
        private Integer age; // 包装类
        // getters and setters
    }
    
    public class TargetBean {
        private int age; // 基本数据类型
        // getters and setters
    }
    
    // 转换代码
    SourceBean source = new SourceBean();
    source.setAge(null);
    
    TargetBean target = new TargetBean();
    org.springframework.beans.BeanUtils.copyProperties(source, target); // 可能抛出NullPointerException
    
  2. 性能考虑:频繁的装箱和拆箱操作会影响性能,尤其是在批量数据处理或高并发场景下。

  3. 类型匹配:确保源Bean和目标Bean的相应属性类型匹配,避免不必要的装箱和拆箱操作,减少性能开销。

最佳实践

  • 字段类型一致性:在设计Bean时,尽量保持相应属性类型一致,以减少装箱和拆箱操作。
  • 使用DTO对象:在复杂的数据转换场景中,考虑使用DTO(数据传输对象)进行中间转换,明确各阶段的数据类型,减少潜在的转换问题。
  • 使用MapStruct:使用MapStruct等代码生成的映射框架,在编译时生成高效的映射代码,可以显著减少运行时的装箱和拆箱操作。

使用MapStruct进行转换

@Mapper
public interface BeanMapper {
    BeanMapper INSTANCE = Mappers.getMapper(BeanMapper.class);

    TargetBean toTargetBean(SourceBean source);
}

public class Main {
    public static void main(String[] args) {
        SourceBean source = new SourceBean();
        source.setAge(25);
        source.setActive(true);

        TargetBean target = BeanMapper.INSTANCE.toTargetBean(source);

        System.out.println("Age: " + target.getAge());
        System.out.println("Active: " + target.getActive());
    }
}

结论

自动装箱和拆箱是Java语言中的重要特性,它们可以简化代码,提高可读性。然而,在实际项目开发中,开发者需要注意性能影响、空指针异常、相等性比较等问题。在Spring Boot应用和Bean转换过程中,自动装箱和拆箱的应用尤为常见。通过合理设计数据结构、使用适当的工具和框架(如MapStruct),以及遵循最佳实践,可以有效避免这些潜在问题,提升代码的质量和运行效率。

参考链接

  1. Oracle 官方文档

    • Java SE Documentation: 提供了Java SE的官方API文档。
    • Autoboxing: Java教程中的自动装箱和拆箱部分。
  2. Spring Framework

    • Spring Framework Documentation: 提供了Spring框架的官方文档。
    • Spring Boot Documentation: Spring Boot的官方文档,涵盖了JSON解析、数据绑定等内容。
  3. Jackson

    • Jackson Project Home: Jackson库的GitHub主页,提供了源代码和使用指南。
    • Jackson Annotations: Jackson的注解库,详细介绍了各种注解的使用方法。
  4. Bean转换工具

    • Spring BeanUtils: Spring框架中BeanUtils类的API文档。
    • Apache Commons BeanUtils: Apache Commons BeanUtils的主页,提供了详细的使用说明和示例。
    • MapStruct: MapStruct的官方网站,包含使用指南和文档。
  5. Java Optional

    • Optional Class: Java SE 11中Optional类的官方文档,介绍了Optional类的使用方法。

在这里插入图片描述

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

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

相关文章

类和对象的学习总结(一)

面向对象和面向过程编程初步认识 C语言是面向过程的&#xff0c;关注过程&#xff08;分析求解问题的步骤&#xff09; 例如&#xff1a;外卖&#xff0c;关注点菜&#xff0c;接单&#xff0c;送单等 C是面向对象的&#xff0c;关注对象&#xff0c;把一件事拆分成不同的对象&…

机器学习笔记——支持向量机

支持向量机 参数模型对分布需要假设&#xff08;这也是与非参数模型的区别之一&#xff09;间隔最大化&#xff0c;形式转化为凸二次规划问题 最大化间隔 间隔最大化是意思&#xff1a;对训练集有着充分大的确信度来分类训练数据&#xff0c;最难以分的点也有足够大的信度将…

-31-()

在终端运行时消除输入空格对程序的影响可以使用{在scanf后加“getchar()”或者在scanf&#xff08;“空格%d”,&a&#xff09;} 按位与和移位操作符只能用于整数且都要转位二进制后进行相应操作 不创建临时变量&#xff0c;实现两个数的交换&#xff1a;1——使用加减法&…

插卡式仪器模块:数据记录模块(插卡式)

• 32 位分辨率 • 250 KSPS 采样率 • 可以同时并且连续地记录两个通道的电压输入 • 实时上传原始数据至 PC 端 通道22输入阻抗电压22 kΩ10 MΩ电流0.2 Ω输入范围电压 250 mV 4.5 V电流1.5 A耦合DCDC带宽450 Hz385 HzADC 分辨率32 Bits24 Bits采样率10 kSPS250 kSPS测量…

【最新鸿蒙应用开发】——类Web开发范式1——生命周期

兼容JS的类Web开发范式 类Web命令式开发的生命周期 1. 应用生命周期 1.1. app.js 每个应用可以在app.js自定义应用级生命周期的实现逻辑&#xff0c;包括&#xff1a; onCreate&#xff1a;在应用生成时被调用的生命周期函数。 onDestroy&#xff1a;在应用销毁时被调用的生…

高德地图简单实现点标,和区域绘制

高德地图开发文档:https://lbs.amap.com/api/javascript-api/guide/abc/quickstart 百度搜索高德地图开发平台 注册高德地图开发账号 在应用管理中 我的应用中 添加一个Key 点击提交 进入高德地图开发文档:https://lbs.amap.com/api/javascript-api/guide/abc/quickstart …

详解FedProx:FedAvg的改进版 Federated optimization in heterogeneous networks

FedProx&#xff1a;2020 FedAvg的改进 论文&#xff1a;《Federated Optimization in Heterogeneous Networks》 引用量&#xff1a;4445 源码地址&#xff1a; 官方实现&#xff08;tensorflow&#xff09;https://github.com/litian96/FedProx 几个pytorch实现&#xff1a;…

【激光雷达】

激光雷达 机械式360扫描雷达半固态激光雷达二维扫描一维扫描 固态激光雷达OPA固态激光雷达&#xff08; 光学相控阵技术&#xff09;Flash激光雷达 FMCW 激光雷达 激光雷达技术在近几年可以说是蓬勃发展&#xff0c;新能源汽车的大量使用&#xff0c;给雷达技术的发展提供了肥沃…

C++系统编程篇——linux编译器 gcc/g++(链接动静态库)

linux编译器-gcc/g &#xff08;1&#xff09;g安装&#xff08;gcc一般自带&#xff0c;g需要下载&#xff09; sudo yum install -y gcc-c g --version gcc用于编译C语言代码&#xff0c;g用于编译C代码 &#xff08;2&#xff09;程序翻译过程 选项“-o”是指目标文件…

Python的else子句7个妙用,原来还能这样用,整挺好!

## 1、条件语句else基础 &#x1f504; 1.1 简单else的常规操作 在Python中&#xff0c;else子句通常跟在if或一系列if-elif之后&#xff0c;提供一个“否则”的情况处理路径。如果前面的所有条件都不满足 &#xff0c;程序就会执行这里的代码块。例如 &#xff0c;检查一个数…

目标检测(R-CNN)系列(Pytorch 26)

一 R-CNN 除了之前描述的单发多框检测之外&#xff0c;区域卷积神经网络&#xff08;region‐based CNN或regions with CNN features&#xff0c; R‐CNN&#xff09;(Girshick et al., 2014)也是将深度模型应用于目标检测的开创性工作之一。下面介绍R‐CNN及其一 系列改进方法…

【JavaEE】Spring Boot MyBatis详解(一)

一.MyBatis的基本概念与相关配置. 1.基本概念 MyBatis是一款优秀的持久层框架&#xff0c;用于简化JDBC的开发。MyBatis本是Apache的一个开源项目iBatis&#xff0c;2010年这个项目由apache迁移到了google code&#xff0c;并且改名为MyBatis. 2013年11月迁移到Github.持久层…

吴恩达2022机器学习专项课程C2W3:2.25 理解方差和偏差(诊断方差偏差正则化偏差方案)

目录 引言名词替代影响模型偏差和方差的因素1.多项式阶数2.正则化参数 判断是否有高偏差或高方差1.方法一&#xff1a;建立性能基准水平2.方法二&#xff1a;建立学习曲线 总结 引言 机器学习系统开发的典型流程是从一个想法开始&#xff0c;然后训练模型。初次训练的结果通常…

SpringSecurity入门(四)

18、权限管理/授权 18.1、针对url配置 配置SecurityConfig package com.wanqi.config;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.bu…

基于STM32的595级联的Proteus仿真

文章目录 一、595级联1.题目要求2.思路3.仿真图3.1 未仿真时3.2 模式A3.2 模式B3.3 故障模式 二、总结 一、595级联 1.题目要求 STM32单片机&#xff0c;以及三个LED灯对应红黄绿灯&#xff0c;IIC的OLED显示屏&#xff0c;温湿度传感器DHT11&#xff0c;两个独立按键和两个5…

复数乘法IP核的使用

一、IP核解析 在这张图片中&#xff0c;我们看到的是一个“Complex Multiplier (6.0)” IP 核的配置界面。以下是各个配置参数的详细说明&#xff1a; 1.1 Multiplier Construction Use LUTs: 选择这个选项时&#xff0c;乘法器将使用查找表&#xff08;LUTs&#xff09;来实现…

【数据分析系列】交叉列联表与卡方检验:数据解读与Python实践应用

目录 一、交叉列联表和卡方检验的关系 &#xff08;一&#xff09;什么是交叉列联表 &#xff08;二&#xff09;什么是卡方检验 &#xff08;三&#xff09;除了卡方检验&#xff0c;列联表分析还可以结合其他统计方法 二、列联表只能用于两个分类变量吗&#xff1f; 三、…

随机点名软件,教师必备NO.106

事先需要新建一个txt文本文档&#xff0c;里面输入名单&#xff0c;一行一个 点击文件-导入TXT-点击开始抽取 资源来源于网络&#xff0c;免费分享仅供学习和测试使用&#xff0c;请勿用于商业用途&#xff0c;如有侵权请联系删除&#xff01; 下载地址&#xff1a;点击查看…

CISCN2023 初赛部分复现

Misc 1. 被加密的生产流量 涉及到modbus协议 modbus && frame.len 66过滤之后&#xff0c;每条流量最后两个字节是base32的密文 脚本一键提取 #modbus_exp import pysharkflag tmp 0 cap pyshark.FileCapture(input_file"D:/下载/CTF附件/ciscn2023/modbu…

js调试过程中修改变量值

1.在想要变更的地方添加断点 2.添加监视表达式 3.执行网页代码&#xff0c;当执行到断点处则会停止 4.点击执行下一步&#xff0c;则会执行监视表达式