【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();
}
相关推荐
励志码农8 小时前
JavaWeb 30 天入门:第二十三天 —— 监听器(Listener)
java·开发语言·spring boot·学习·servlet
天高云淡ylz8 小时前
子网掩码的隐形陷阱:为何能ping通却无法HTTPS访问
开发语言·php
@小匠8 小时前
Spring Cache 多租户缓存隔离解决方案实践
java·spring·缓存
智码看视界9 小时前
老梁聊全栈系列:(阶段一)架构思维与全局观
java·javascript·架构
黎宇幻生9 小时前
Java全栈学习笔记33
java·笔记·学习
希望201710 小时前
Golang Panic & Throw & Map/Channel 并发笔记
开发语言·golang
朗迹 - 张伟10 小时前
Golang安装笔记
开发语言·笔记·golang
yzx99101310 小时前
生活在数字世界:一份人人都能看懂的网络安全生存指南
运维·开发语言·网络·人工智能·自动化
小周同学@10 小时前
谈谈对this的理解
开发语言·前端·javascript
橙*^O^*安11 小时前
Go 语言基础:变量与常量
运维·开发语言·后端·golang·kubernetes