现在的位置: 首页 > 综合 > 正文

理解java传值还是传引用

2013年04月03日 ⁄ 综合 ⁄ 共 2524字 ⁄ 字号 评论关闭

 

/**
*探究值传递与引用传递
* 看了好多关于java值传递和引用传递的文章,深感迷惑
* 所以就自己看看大虾们的思路,自己用代码动手实验,
* 感觉挺爽的。
* @author java魔人
* 2009-07-20 下午
*/

public class Test {

// method1
public static void changValue1(int a, int b) {
  int c = a;
  a = b;
  b = c;
}

// method2(从结果来看:显而易见:值传递)
public static void print1() {
  int x = 0;
  int y = 1;
  changValue1(x, y); // 传递的是值得coapy,x,y自身没变化。
  System.out.println("x=" + x); // 输出:x=0
  System.out.println("y=" + y); // 输出:y=1
}
/**
  * 个人总结:以上方法没有完成我们的理想。仔细分析如下,看看内存中的存储方式:
  * method2方法的两个成员变量:
  * 变量       内存
  *  x--------->[值0]
  *  y--------->[值1]
  *  调用changValue(x,y)时,内存中是这样的情景:
  *  x------>[值0]
  *    (一次复制)
  *  a------>[值0]
  *  y同理
  *  此时,好像与x,y没什么关系了啊。
  *
  */

// method3
public static void changeValue2(StringBuffer a) {
  a.append(" zhangxiangrong");
}

// method4(从结果来开:应该是引用传递)
public static void print2() {
  StringBuffer sb = new StringBuffer("I'm");
  changeValue2(sb); // 传递的是引用,所以执行完后,sb的值不再是"I'm"了。
  System.out.println("sb=" + sb.toString()); // 输出:I'm zhangxiangrong
}
/**
  * 个人总结:这个和上面的例子貌似差不多,但可以改变sb的的值。看看内存中情景
  * 开始:
  * sb---------->[值"I'm"]
  * 调用changeValue2(StringBuffer a)时,就大变样了,(因为不是拷贝了)
  * sb---------->[值"I'm"]<--------------a
  * a.append(" zhangxinagrong")时,就变成:
  * sb---------->[值"I'm zhangxiangrong"]<----------a
  * 最终结果,自然sb的值被改变了。
  *  /


// method5
public static void changeValue3(StringBuffer a) {
  System.out.println("a=" + a.toString()); //a=sb1
  StringBuffer b = a;
  System.out.println("b1=" + b.toString()); //b1=sb1
  a.append(" add Str1");
  System.out.println("b2=" + b.toString()); //b2=sb1 add Str1
  a = b;

}
//method6
public static void print3() {
  StringBuffer x = new StringBuffer("sb1");
  changeValue3(x);
  System.out.println("x=" + x.toString()); //x=sb1 add Str1
}

/**
  * 对以上总结:
  * 对于参数传递,如果是简单数据类型,那么它传递的是值拷贝。
  * 对于类的实例它传递的是类的引用。
  * 需要注意的是,这条规则只适用于参数传递。
  *
  */

//test1(传的是引用,很好理解)
public static void test1(){
  StringBuffer x1=new StringBuffer("Hello");
  change1(x1);
  System.out.println("x1="+x1.toString()); //x1=Hello world!
}
public static void change1(StringBuffer sb){
  sb.append(" zhangxiangrong!");
}

//test2
public static void test2(){
  StringBuffer x2=new StringBuffer("Hello");
  change2(x2);
  System.out.println("x2="+x2.toString()); //x2=Hello
}
public static void change2(StringBuffer sb){
  sb=new StringBuffer("hi");
  sb.append(" zhangxiangrong");
}
/**
  * test2研究一下(内存研究挺爽的)
  * x2--------->["Hello"]
  * 调用change2(x2)
  * x2--------->["Hello"]<---------sb
  * new 的出现开辟内存空间["hi"],接着
  * sb--------->["hi"](原来的指向剪断)
  * 此时和x2拜拜了,没什么关系了。 x2--------->["Hello"](不变)
  * 结论:
  * 对于函数调用,最终效果是什么完全看函数内部的实现。
  * 比较标准的做法是如果会改变引用的内容,
  * 则使用void作为方法返回值,
  * 而不会改变引用内容的则在返回值中返回新的值。
  */

//main
public static void main(String args[]) {
  print1();
  print2();
  print3();
  
  test1();
  test2();
}

}

抱歉!评论已关闭.