java的参数传递确实有点绕人,简单研究了一下,
public class Test { public static void main(String[] args) { char[] ch = { 'H', 'e', 'l', 'l', 'o' }; change(ch); System.out.print("ch[]:"); System.out.println(ch); // ch[]:Cello ////传递的是数组首地址,则是传址调用,形参与实参指向同一块内存空间, ///所以形参指向的值改变后,实参的值同样也会改变 changeElement(ch[1]); System.out.println(ch); // /Cello ////传递的是数组元素,不是地址,则是传值调用,形参的值改变对实参的值无影响 String str1 = "Hello"; String str2 = changStr(str1); System.out.println("str1:" + str1); // str1:Hello System.out.println("str2:" + str2); // str2:Cello///返回值赋值给一个新的String对象 /////String对象和基本类型一样,是传值调用,形参的值改变对实参的值无影响 int n = 3; System.out.println("Before change, n = " + n);// Before change, n = 3 changeData(n); System.out.println("After changeData(n), n = " + n);// After changeData(n), n= 3 /////String对象和基本类型一样,是传值调用,形参的值改变对实参的值无影响 } public static void change(char ch[]) { ch[0] = 'C'; } public static void changeElement(char c) { c = 'w'; } public static String changStr(String str) { str = "Cello"; return str; } public static void changeData(int nn) { // ///---1 // nn = 10; // System.out.println("nn="+nn); ///nn=10///第一种情况:形参nn的值是实参n的值都为3,nn后又赋值为10,则nn=10 // //------2 System.out.println("nn=" + nn); // /nn=3 ///第二种情况:不对形参nn赋其他值,则nn=3 } } //ch[]:Cello //Cello //str1:Hello //str2:Cello //Before change, n = 3 //nn=3 //After changeData(n), n = 3--------------------------------------------------------------------------------------------------------
public class Test3 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello "); System.out.println("Before change, sb = " + sb);////Before change, sb = Hello changeData(sb); System.out.println("After changeData(n), sb = " + sb);////After changeData(n), sb = Hello World! } public static void changeData(StringBuffer strBuf) { strBuf.append("World!"); System.out.println("strBuf = " + strBuf);///strBuf = Hello World! ///strBuf与sb指向同一个StringBuffer, ///若strBuf使StringBuffer内容改变则sb指向的StringBuffer内容也同样改变 } } //Before change, sb = Hello //strBuf = Hello World! //After changeData(n), sb = Hello World!------------------------------------------------------------------------------------------------------------
public class Test4 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello "); System.out.println("Before change, sb = " + sb);////Before change, sb = Hello changeData(sb); System.out.println("After changeData(n), sb = " + sb);//After changeData(n), sb = Hello } public static void changeData(StringBuffer strBuf) { StringBuffer sb2 = new StringBuffer("Hi "); strBuf = sb2; sb2.append("World!"); System.out.println("sb2 = " + sb2);//sb2 = Hi World! ///strBuf一开始与sb指向同一个StringBuffer,在changeData()中new 了一个新的StringBuffer, ///strBuf = sb2; 则使strBuf指向sb2所指向的新的StringBuffer,strBuf指向的StringBuffer的值改变,对sb所指向的StringBuffer的值无影响 } } //Before change, sb = Hello //sb2 = Hi World! //After changeData(n), sb = Hello
----------------------------------------------------------------------------------------------------------
class Value { public int i = 15; } public class Test { public static void main(String[] args) { // TODO Auto-generated method stub Test t = new Test(); t.first(); } public void first() { int i = 5; Value v = new Value(); v.i = 25; second(v, i); System.out.println(v.i); } public void second(Value v, int i) {////注意这里的形参v与实参v是两个变量,只是名称相同 i = 0; v.i = 20; Value val = new Value(); v = val; System.out.println(v.i + " " + i); } } //输出:15 0 20 ,有些人不理解??做下变种:
public void second(Value v2, int i) { i = 0; v2.i = 20; Value val = new Value(); v2 = val; System.out.println(v2.i + " " + i); }
这样清晰了很多,
解析看图片:
/////对象,StringBuffer,数组名或数组首地址是传址调用
/////基本类型、String,是传值调用
//关于书上的地址的副本和值的副本那些个人觉得理解起来有些吃力,还是喜欢C里的说法
//String类是个特殊的类,对它的一些操作符是重载的,如:
//String str = “Hello”; 等价于String str = new String(“Hello”);
//-------------------------------
//String str = “Hello”;
//str = str + “ world!”;等价于str = new String((new StringBuffer(str)).append(“ world!”));
//因此,你只要按上面的方法去分析,就会发现String对象和基本类型一样,一般情况下是传值调用
运行环境:win7 64,eclipse kepler,