今天作项目,发现了一个问题,当String做为参数传递的时候,在函数内部改变值对外部的变量值无影响,以下代码:java
public static void main(String[] args) { String str = "11111"; changeStr(str); System.out.println(str);//输出11111 } public static void changeStr(String str){ str = "22222"; }
一开始很不解,后来想明白了,遂去对java参数传递作一个总结,以加深本身的基础知识.函数
对于:测试
四类八种基本类型来讲,传递的都是值,由于这些值是直接保存在栈内存中的,因此传递的时候直接拷贝过去了.spa
public static void main(String[] args) { int num = 0; change(num); System.out.println(num);//输出0 } public static void change(int numChange){ numChange =5; }
结构以下图,也所以最外层的num的值并无受到影响.code
对象传递,本质上也都是值传递,只不过传递的值是该引用的拷贝.看下面实例和图解:对象
public static void main(String[] args) { Person person = new Person("aaa", 11); change(person); System.out.println(person);//输出 bbb 11 } public static void change(Person personChange){ personChange.setName("bbb"); }
结构图以下:
当执行change的时候,会把person变量的指向的地址拷贝一份给personChange,二者都指向同一个堆内存,即便后面作了set方法修改,可是对二者的执行毫无影响.blog
例二和以前的不一样之处在change里面,对personChange进行了new操做.代码以下:内存
public static void main(String[] args) { Person person = new Person("aaa", 11); change(person); System.out.println(person);//输出 aaa 11 } public static void change(Person personChange){ personChange = new Person("bbb",12); }
结构图以下:博客
当执行change的时候,会把person变量的指向的地址拷贝一份给personChange,二者都指向同一个堆内存,接下new操做会在堆中从新建立一个person对象,此时personChange则指向这个对象,而原person的指向没发生变化,故输出aaa 11.class
例三是综合例一和例二,前面两个搞懂的话这个就很容易懂了.
public static void main(String[] args) { Person person = new Person("aaa", 11); change(person); System.out.println(person);//输出 ccc 11 } public static void change(Person personChange){ personChange.setName("ccc"); personChange = new Person("bbb",12); }
结构图以下:
读者本身理解下,不懂的话再看看前面的,看看为何输出CCC 11
终于到最初的问题,为何String是对象,可是却不符合上面对象传递测试出来的结果?
public static void main(String[] args) { String str = "11111"; changeStr(str); System.out.println(str);//输出11111 } public static void changeStr(String str){ str = "22222"; }
缘由:
由于String对象具备不可变性,因此针对操做str = "22222",在String池中不存在的时候,就是至关于str = new String(),这样变化下的话,那么就和例一 如出一辙了,具体图就不画了,但愿对你有帮助.
ps:若是想改变的话,可使用Holder包装类包装String,能够参考博文:Java基础系列18:Holder技术的实现原理分析 | zifangsky的我的博客
要理解上面的结果,就要认为Java中只有值传递: