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

深入引用的例子
class Demo{
int x=10;
}
public class Demo1 {
public static void main(String args[]){
Demo d=new Demo();
d.x=30;
fun(d);
System.out.println(d.x);
}
public static void fun(Demo temp){
temp.x=100;
}
}





public class Demo2 {
public static void main(String args[]){
String str = "hello"; 
fun(str);
System.out.println(str);
}
public static void fun(String temp){
temp="world";
}
}
以上两个例子第一个输出是100第二个是hello,不是说对内存一旦定下来就不可修改么?为什么好像第一个例子的x可修改,第二个的str不可修改,大神们求助啊!

------解决方案--------------------
你说的内存不可修改的应该是指字符串吧?字符串一旦定下来就不能修改,若要储存不同的字符串,就要重新开辟内存空间
class Demo{
int x=10;
}
public class Demo2 {
public static void main(String args[]) {
String str = "hello";
System.out.println("hello  hashcode:"+str.hashCode());
fun(str);
System.out.println("finally hashcode:"+str.hashCode());
System.out.println(str);
}

public static void fun(String temp) {
System.out.println("before change hashcode:"+temp.hashCode());
temp = "world";
System.out.println("after change hashcode:"+temp.hashCode());
}
}


输出:
hello  hashcode:99162322
before change hashcode:99162322
after change hashcode:113318802
finally hashcode:99162322
hello

------解决方案--------------------
Demo:传递Demo对象的引用,也就是将地址复制到栈中,利用栈中的这个引用修改值,自然是成功的。失败的例子是:
temp = new Demo(); temp.x = 100;
Demo2:类似于上面失败的例子,temp指向了一个新的内存空间“ world ”,由于temp是在栈中的,所以不会修改原来的值
------解决方案--------------------
Java中的变量除了基本类型之外的String、Object、数组等这些类型作为方法参数时都是引用参数,类似于C中的指针(类似,但不是)
所以不难理解Demo1中的fun方法

那么Demo2中的fun方法传入的是一个String类型,它仍然是引用类型,但是为什么不能改变呢?是因为Java中字符串拼接会产生一个新的字符串,而不是在原来的基础上进行增加,这样以来,temp="world";之后,实际上temp所代表的内存位置改变了,而这个改变是不会反映到func方法外,就像在C语言中
void func(char *temp) {temp = "world";}
函数返回后,temp指针的指向并不会发生变化
如果需要改变temp的指向,那么必须传入指向temp的指针,如下
void func(char **temp) {*temp = "world";}
这样一来,函数返回后temp的指向便改变到"world"
当然,上面说的可能有些跑题,但是这样这比较分析会加深理解

既然说到了C语言,那么就多说一点,实际上向C语言函数中传递一个值和一个指针其实都是一样的,都是值传递,只是传递一个指针时可以通过这个指针修改指针指向的值,而且这个修改在函数返回后仍然保留。如果说只是修改这个指针的指向,那么和普通的值传递是没有区别的,即在函数返回后指针的指向改变不会保留。

那么回到之前的Demo2的func方法,如果说需要实现类似Demo1的修改怎么办?
使用一个包装了String的对象引用,例如StringBuilder,或者自己实现一个类,类的一个对象域是你需要修改的String变量。