【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();
}
相关推荐
Boilermaker19925 小时前
[Java 并发编程] Synchronized 锁升级
java·开发语言
Cherry的跨界思维6 小时前
28、AI测试环境搭建与全栈工具实战:从本地到云平台的完整指南
java·人工智能·vue3·ai测试·ai全栈·测试全栈·ai测试全栈
MM_MS6 小时前
Halcon变量控制类型、数据类型转换、字符串格式化、元组操作
开发语言·人工智能·深度学习·算法·目标检测·计算机视觉·视觉检测
꧁Q༒ོγ꧂6 小时前
LaTeX 语法入门指南
开发语言·latex
njsgcs6 小时前
ue python二次开发启动教程+ 导入fbx到指定文件夹
开发语言·python·unreal engine·ue
alonewolf_996 小时前
JDK17新特性全面解析:从语法革新到模块化革命
java·开发语言·jvm·jdk
一嘴一个橘子6 小时前
spring-aop 的 基础使用(啥是增强类、切点、切面)- 2
java
sheji34166 小时前
【开题答辩全过程】以 中医药文化科普系统为例,包含答辩的问题和答案
java
古城小栈7 小时前
Rust 迭代器产出的引用层数——分水岭
开发语言·rust
ghie90907 小时前
基于MATLAB的TLBO算法优化实现与改进
开发语言·算法·matlab