博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java 变量参数传入方法,修改后是否影响外面的值
阅读量:2715 次
发布时间:2019-05-13

本文共 3713 字,大约阅读时间需要 12 分钟。

public class Test2 {    public static void setValue(String str){        str = "ss";    }    public static void setValue(Man str){        str = new Man("test");    }    public static class Man{        private String name;        public String getName() {            return name;        }        public void setName(String name) {            this.name = name;        }        public Man(String name) {            this.name = name;        }        @Override        public String toString() {            return "Man{" +                    "name='" + name + '\'' +                    '}';        }    }    public static void main(String[] args) {        String str = "s";        setValue(str);        System.out.println(str);        Man man = null;        setValue(man);        System.out.println(man);    }}

如上面代码实践,结果输出 

snull

原因是方法在执行的时候有栈帧的概念,入栈的时候只是压栈方法参数是传入参数的副本。

JVM高级特性

此时区分数据类型:基本类型和引用类型

基本类型:值存放在局部变量表中,无论如何修改只会修改当前栈帧的值,方法执行结束对方法外不会做任何改变;此时需要改变外层的变量,必须返回主动赋值。

引用数据类型:指针存放在局部变量表中,调用方法的时候,副本引用压栈,赋值仅改变副本的引用但是如果直接改变副本引用的值,修改了引用地址的对象,此时方法以外的引用此地址对象当然被修改。(两个引用,同一个地址,任何修改行为2个引用同时生效)

比如

public static void setValue(StringBuilder str){        str = new StringBuilder("sss");    }        public static void setValue2(StringBuilder str){        str.append("sss");    }    public static void main(String[] args) {        StringBuilder str = new StringBuilder();        setValue(str);        System.out.println(str.toString()); //输出空字符串        setValue2(str);        System.out.println(str.toString()); //输出sss    }

关于String,本质是final类型char数组,不可修改,只能赋值,在做参数传入方法修改时,其实是新建对象,必须返回重新对外面的变量赋值才会对外面的String引用生效。

看String源码的任意一个方法即可明白

/**     * Returns a string resulting from replacing all occurrences of     * {@code oldChar} in this string with {@code newChar}.     * 

* If the character {@code oldChar} does not occur in the * character sequence represented by this {@code String} object, * then a reference to this {@code String} object is returned. * Otherwise, a {@code String} object is returned that * represents a character sequence identical to the character sequence * represented by this {@code String} object, except that every * occurrence of {@code oldChar} is replaced by an occurrence * of {@code newChar}. *

* Examples: *

     * "mesquite in your cellar".replace('e', 'o')     *         returns "mosquito in your collar"     * "the war of baronets".replace('r', 'y')     *         returns "the way of bayonets"     * "sparring with a purple porpoise".replace('p', 't')     *         returns "starring with a turtle tortoise"     * "JonL".replace('q', 'x') returns "JonL" (no change)     * 
* * @param oldChar the old character. * @param newChar the new character. * @return a string derived from this string by replacing every * occurrence of {@code oldChar} with {@code newChar}. */ public String replace(char oldChar, char newChar) { if (oldChar != newChar) { int len = value.length; int i = -1; char[] val = value; /* avoid getfield opcode */ while (++i < len) { if (val[i] == oldChar) { break; } } if (i < len) { char buf[] = new char[len]; for (int j = 0; j < i; j++) { buf[j] = val[j]; } while (i < len) { char c = val[i]; buf[i] = (c == oldChar) ? newChar : c; i++; } //String的value 是final char[],一旦创建不能改变 return new String(buf, true); } } return this; }

引用类型会引起浅拷贝和深拷贝现象。

你可能感兴趣的文章
Linux设备驱动开发详解-第4章(三)-导出符号
查看>>
Linux设备驱动开发详解-第6章字符设备驱动(一)-globalmem
查看>>
Linux设备驱动开发详解-第6章字符设备驱动(二)-支持2个globalmem
查看>>
Linux进程状态浅析
查看>>
安装QT, 执行qt-sdk-linux-x86-opensource-2010.05.bin
查看>>
linux下如何统计一个目录下的文件个数以及代码总行数的命令
查看>>
屏蔽Qt的qDebug()语句输出
查看>>
解决QWidget: Cannot create a QWidget when no GUI is being used
查看>>
解决eclipse复制代码到word中没有颜色的难题
查看>>
Android新浪微博客户端—开篇
查看>>
2016年4月~2017年7月 创业经验总结
查看>>
copy-on-write(写时复制)
查看>>
IO端口和IO内存
查看>>
ioremap函数解析
查看>>
ioremap()的原理及意义
查看>>
source insight4.0支持.cc文件
查看>>
linux查看终端进程占用资源
查看>>
Makefile学习教程: 跟我一起写 Makefile
查看>>
arm-linux-gcc/ld/objcopy/objdump参数总结
查看>>
MultimediaAnalyzer项目实战-启动项目
查看>>