文章目录
- 前言
- 失败的修改
- 成功的修改
- 原理分析
- 基本类型参数
- 对象引用参数
- 举一反三:不修改对象参数怎么写?
前言
今天写代码的时候,犯了一个很基础很低级的错误。实在惭愧,在此花点顺手记录一下,养成习惯。
需求是需要把byte[]作为入参的同时,也作为出参,传一个空白的byte[]作为参数,在方法里面修改byte[],修改完毕后,外面方法获取到被修改后的参数,很简单吧。
失败的修改
new 一个byte[],然后改为全零,再打印看看是否成功:
@Testpublic 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));}
输出:
before: bytes = [1, 2, 3]
changeBytes2 before bytes = [1, 2, 3]
changeBytes2 after bytes = [0, 0, 0]
after changeBytes2: bytes = [1, 2, 3]
可以看到,数组修改失败。
成功的修改
@Testpublic 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);}
打印结果:
before: bytes = [1, 2, 3]
after changeBytes: bytes = [0, 0, 0]
bytes数据成功被修改。
原理分析
基本类型参数
在 Java 中,传递给方法的参数是按值传递的,这意味着方法得到的是参数的副本,而不是参数本身。对于基本数据类型,这意味着方法得到的是值的拷贝,对参数的修改不会影响调用者的变量。
对象引用参数
但是对于对象引用(包括数组),方法得到的是引用的拷贝,这意味着方法内部可以修改对象的内容,并且这些修改将影响到调用者持有的引用。所以,无论你传递的是数组、集合对象或者是其他对象,只要你在方法内部修改了这个对象的内容,这些修改都会影响到调用者持有的引用。
举一反三:不修改对象参数怎么写?
如果你想要避免对调用者持有的对象产生影响,可以创建一个新的对象,并将修改后的内容复制到新对象中,然后返回这个新对象。这样调用者将得到一个新的对象,原始对象不会受到影响。
举个例子,如果要修改的是一个字符串对象,你可以使用 StringBuilder
类来构建一个新的字符串:
private String changeString(String originalString) {StringBuilder sb = new StringBuilder(originalString);sb.append(" additional content");return sb.toString();
}