日期:2014-05-20  浏览次数:20602 次

关于函数参数的引用和复制
有如下程序,对于部分参数在调用函数时被复制(如:String,   arry,   Object(可能Object不算));有些被引用(如:HashMap)

想问下,那些类型的变量调用函数时被复制,哪些被引用?
多谢先!

--------------
import   java.util.HashMap;

public   class   Test1   {

public   static   void   main(String[]   args)   {
String   s= "s1 ";
Object   o   =   "o1 ";
int[]   a   =   new   int[]{1,2,3};
HashMap   h   =   new   HashMap();
h.put( "h1 ",   "v ");
f(s,   o,   a,   h);
System.out.println( "string= "   +   s);
System.out.println( "object= "   +   o);
System.out.println( "array= "   +   a.length);
System.out.println( "hashmap= "   +   h.size());
}

static   void   f(String   s,   Object   o,   int[]   a,   HashMap   h){
s   += "__ ";
o   =   "222 ";
a   =   new   int[]{1,2,3,4};
h.put( "2 ",   "v2 ");
}
}

-----------结果:
string=s1
object=o1
array=3
hashmap=2


------解决方案--------------------
楼主如果有一些c的基础也许容易理解一些。在java里面, 函数调用时, 参数传递的简单类型(int, char等)会被复制, 因此在函数中对这些参数的修改在函数退出是会丢失。参数传递的对象类型实际上传递的是引用, 也就是指针, 指针的本质也是一个整数, 因此这个引用会被复制一份, 但是这个引用指向的对象不会被复制。因此, 在函数中, 通过参数对对象的操作不会丢失, 但是对这个引用的重新赋值会丢失。 在你的代码中,

s += "__ "; //这个是对s的重新赋值, 丢失
o = "222 "; //同上
a = new int[]{1,2,3,4}; //同上
h.put( "2 ", "v2 "); //通过引用来操作对象, 不会丢失

------解决方案--------------------
只要不是简单类型就会被引用,String和HashMap不同的地方是String是一个内容不可改变的对象,就是说如果你想改变一个String,你得到必然是一个新的String
可以看看lz的代码对4个变量的操作,前3个都是在赋值,最后是对map的put
f(String s, Object o, int[] a, HashMap h) 在调用这个方法的时候,s,o, a, h是在栈中的临时变量,也就是说只有在

这个方法的生命周期内才有效,(lz做c很多年应该知道传值和传地址的区别吧, 指针也是变量只不过我们操作他的规则很特

殊), 对前3个变量的操作都是对变量本身的操作(赋值), 没有对他们指向的对象做操作,又能期望那些对象有什么改变呢?
而对第4个的操作是对h这个变量指向的对象的操作( map.put() )
如果对第4个变量的操作也是h=new HashMap(); 那么结果就是什么也没有变化
------解决方案--------------------
to 楼主:

只要是类的实例,就不会被复制,String也一样,没有特殊性。数组虽然不是类的实例,但也是做为对象而存在的,所以也不会被复制。

被复制的类型只有简单类型,具体地说,是boolean, char, byte, short, int, long, float, double这八种。

另外,对象的引用(JAVA中叫引用,其实就是对象的地址,相当于C++的指针)本身是被复制的。这和C++中的指针会被复制是一个道理。

本质上,JAVA中所有的赋值操作以及函数的参数传递及值返回都是复制的。但对于简单类型和非简单类型,其复制的内容有所不同,对于简单类型复制的是对象本身,而对于非简单类型复制的是对象的地址。JAVA不允许程序员自己来选择是复制对象本身还是复制地址。

C++新手,有时甚至是有经验的程序员也往往要花大量时间来研究复制控制,而JAVA简化了所有的这些。在JAVA中,你只要记住:简单类型和地址永远是复制的,而除此之外都是不复制的。

JAVA提供一个复制非简单类型的方法,clone(),但这个方法也是复制对象的表层,对于所有的非简单类型对象成员都是复制其地址,clone()是一种“浅复制”。
------解决方案--------------------
全部都是引用。

string=s1 //因为函数中用=重新赋值了(new了新实例),改变了地址,不再指向原来实例了,下同
object=o1
array=3
hashmap=2 //因为函数中调用了类似于设置之类的方法,改变了内容

------解决方案--------------------
xingyue2003() ( ) 信誉:100 Blog 2007-3-7 8:32:01 得分: 0



java的基本类型和string的对象会被复制,其他的是引用,如果前者是数组的话也是引用,因为数组可以被看作是array对象
---------------------------------
不要误导人家,只有基本类型才是复制,String是类不会被复制.数组在java里是和类一样的不会被复制.