Java参数传递,传递引用,传递值浅析

简而言之,基础数据类型(int,char,……)传值,对象类型(Object,数组,容器,StringBuffer……)传引用。但是对于String, Integer, Double等等immutable的类型,也是传值需要特殊处理。

三句话总结一下:

1.对象就是传引用

2.原始类型就是传值

3.String,Integer, Double等immutable类型因为没有提供自身修改的函数,每次操作都是新生成一个对象,所以要特殊对待。可以认为是传值。

Integer 和 String 一样。保存value的类变量是Final属性,无法被修改,只能被重新赋值/生成新的对象。 当Integer 做为方法参数传递进方法内时,对其的赋值都会导致 原Integer 的引用被 指向了方法内的栈地址,失去了对原类变量地址的指向。对赋值后的Integer对象做得任何操作,都不会影响原来对象。

参考:https://blog.csdn.net/yangliuy/article/details/43230681

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);
}

这样清晰了很多,

解析看图片:

Java参数传递,传递引用,传递值浅析_第1张图片

 

对象,StringBuffer,数组名或数组首地址是传址调用
基本类型(int,char等)、String、Integer、Long等是传值调用
//关于书上的地址的副本和值的副本那些个人觉得理解起来有些吃力,还是喜欢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,

你可能感兴趣的:(Java,java,函数,参数,引用)