【Java】Java的对象参数踩坑总结

文章目录

前言

今天写代码的时候,犯了一个很基础很低级的错误。实在惭愧,在此花点顺手记录一下,养成习惯。

需求是需要把byte[]作为入参的同时,也作为出参,传一个空白的byte[]作为参数,在方法里面修改byte[],修改完毕后,外面方法获取到被修改后的参数,很简单吧。

失败的修改

new 一个byte[],然后改为全零,再打印看看是否成功:

java 复制代码
   @Test
    public void invoke(){
        byte[] bytes = new byte[]{1,2,3};
        System.out.println("before: bytes = " + Arrays.toString(bytes));
        /*changeBytes(bytes);
        System.out.println("after changeBytes: bytes = " + Arrays.toString(bytes));*/

        changeBytes2(bytes);
        System.out.println("after changeBytes2: bytes = " + Arrays.toString(bytes));
    }
    
 private void changeBytes2(byte[] bytes) {
        System.out.println("changeBytes2 before bytes = " + Arrays.toString(bytes));
        bytes = new byte[]{0,0,0};
        System.out.println("changeBytes2 after bytes = " + Arrays.toString(bytes));
    }
    

输出:

bash 复制代码
before: bytes = [1, 2, 3]
changeBytes2 before bytes = [1, 2, 3]
changeBytes2 after bytes = [0, 0, 0]
after changeBytes2: bytes = [1, 2, 3]

可以看到,数组修改失败。

成功的修改

java 复制代码
  @Test
    public void invoke(){
        byte[] bytes = new byte[]{1,2,3};
        System.out.println("before: bytes = " + Arrays.toString(bytes));
        changeBytes(bytes);
        System.out.println("after changeBytes: bytes = " + Arrays.toString(bytes));

        /*changeBytes2(bytes);
        System.out.println("after changeBytes2: bytes = " + Arrays.toString(bytes));*/
    }

    private void changeBytes(byte[] bytes) {
        Arrays.fill(bytes, (byte) 0);
    }

打印结果:

java 复制代码
before: bytes = [1, 2, 3]
after changeBytes: bytes = [0, 0, 0]

bytes数据成功被修改。

原理分析

基本类型参数

在 Java 中,传递给方法的参数是按值传递的,这意味着方法得到的是参数的副本,而不是参数本身。对于基本数据类型,这意味着方法得到的是值的拷贝,对参数的修改不会影响调用者的变量。

对象引用参数

但是对于对象引用(包括数组),方法得到的是引用的拷贝,这意味着方法内部可以修改对象的内容,并且这些修改将影响到调用者持有的引用。所以,无论你传递的是数组、集合对象或者是其他对象,只要你在方法内部修改了这个对象的内容,这些修改都会影响到调用者持有的引用。

举一反三:不修改对象参数怎么写?

如果你想要避免对调用者持有的对象产生影响,可以创建一个新的对象,并将修改后的内容复制到新对象中,然后返回这个新对象。这样调用者将得到一个新的对象,原始对象不会受到影响。

举个例子,如果要修改的是一个字符串对象,你可以使用 StringBuilder 类来构建一个新的字符串:

java 复制代码
private String changeString(String originalString) {
    StringBuilder sb = new StringBuilder(originalString);
    sb.append(" additional content");
    return sb.toString();
}
相关推荐
Goldn.16 分钟前
Java核心技术栈全景解析:从Web开发到AI融合
java· spring boot· 微服务· ai· jvm· maven· hibernate
李慕婉学姐1 小时前
【开题答辩过程】以《基于Android的出租车运行监测系统设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·后端·vue
小鸡吃米…1 小时前
Python 列表
开发语言·python
m0_740043731 小时前
SpringBoot05-配置文件-热加载/日志框架slf4j/接口文档工具Swagger/Knife4j
java·spring boot·后端·log4j
编织幻境的妖1 小时前
SQL查询连续登录用户方法详解
java·数据库·sql
kaikaile19952 小时前
基于C#实现一维码和二维码打印程序
开发语言·c#
我不是程序猿儿2 小时前
【C#】画图控件的FormsPlot中的Refresh功能调用消耗时间不一致缘由
开发语言·c#
未若君雅裁2 小时前
JVM面试篇总结
java·jvm·面试
rit84324992 小时前
C# Socket 聊天室(含文件传输)
服务器·开发语言·c#
kk哥88992 小时前
C++ 对象 核心介绍
java·jvm·c++