【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();
}
相关推荐
曾经的三心草20 分钟前
基于正倒排索引的Java文档搜索引擎3-实现Index类-实现搜索模块-实现DocSearcher类
java·python·搜索引擎
dangdang___go24 分钟前
动态内存管理||malloc和free.realloc和calloc
c语言·开发语言·算法·动态内存管理
l***466824 分钟前
SSM与Springboot是什么关系? -----区别与联系
java·spring boot·后端
稚辉君.MCA_P8_Java24 分钟前
Gemini永久会员 快速排序(Quick Sort) 基于分治思想的高效排序算法
java·linux·数据结构·spring·排序算法
I***t71629 分钟前
【MyBatis】spring整合mybatis教程(详细易懂)
java·spring·mybatis
YA33334 分钟前
mcp-grafana mcp 使用stdio报错
java·开发语言
周杰伦_Jay37 分钟前
【Go 语言主流 Web】 框架详细解析
开发语言·后端·微服务·架构·golang
z***026039 分钟前
SpringBoot创建动态定时任务的几种方式
java·spring boot·spring
w***95491 小时前
VScode 开发 Springboot 程序
java·spring boot·后端
兔子撩架构1 小时前
Dubbo 的同步服务调用
java·后端·spring cloud