首先说明普遍说的值传递是指把传递的实际参数值复制一份到调用函数中,这样对函数值无法进行修改;这个很简单,容易理解,就不说了;其次应用传递是说,把实际参数地址传递到调用函数中,这样的修改将有可能影响到主调函数,分为两种情况;举个例子说一下,例一见下面图片:


java 接口 map对象如何传 java map引用传递_初始化

输出结果是:lee

方法执行是这样的,首先main方法进入stack中,然后new 了一个User对象,于是jvm在heap中就创建了一个新的对象,该对象的地址假设是0x81,在调用pass(u)这个方法时,就把0x81传递给pass1()方法,于是这时相当于pass1()方法中u指向了heap中的0x81,于是对内容的修改会影响到main方法的name值,pass1()方法执行完后离开stack,但是heap中内存已经受到影响。

例二,如下图:


java 接口 map对象如何传 java map引用传递_初始化_02

输出结果是:Gem

这个程序执行的顺序是这样的,首先main()方法进入stack,new User,这时jvm就在heap中开辟一个内存空间,假设地址是0x81,然后再调用pass2()方法,这时,pass2()方法进入stack中,这一句u = new User(),这时jvm会再在heap中开辟一个内存空间,假设地址是0x82,并把它的地址值,复制一份给u。在pass2()方法里面如果输出u.getName()的话,一定是gemlee,因为在stack中,u的内存存储的地址值就是0x82,但是等程序执行完毕,pass2()方法就会离开stack,同时pass2()中变量u的值也会离开,而main()方法中的值根本没有影响。所以在java核心技术卷里说java中一切传值都是值传递,不存在引用传递;

有人关于String传值,有争议,其实去看看源码就好了,String类的初始化,一开始便会初始化一个无法更改的char数组:

/** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0

所以在后续的操作中,只要你这样写:

String s = "name";
s = "abc";

就在jvm是这个表现,会首先初始化一块内存假设地址是0x81,然后,你又赋值的时候,"abc"实际是在内存中又开辟了一块内存空间,原本的"name"就变成垃圾了,但是你的赋值改变不了原来的"name",只是重新开辟了一份内存空间。所以每一次给变量赋值,就是一次重新开辟内存空间,String会造成内存浪费,StringBuffer就不会重新开辟空间