结论:
1. 对于值传递,如int, long等基本类型,不管传入方法后怎么修改,都改变不了方法外面的值。
2. 对于引用传递,如果传入方法后指向了一个新的对象,那么无论怎么修改也改变不了方法外面的对象。
如果传入方法后没有指向新对象,直接操作,就会改变方法外面的对象,因为这是在操作同一个对象。
来看一段测试源码:
package aa;
public class TestObjDelivery {
/**
* @param args
*/
public static void main(String[] args) {
//Test 1
String srcStr = new String("src");
print(srcStr);
changeStr(srcStr);
print(srcStr);
//Test 2
int srcInt = 10;
print("int: " + srcInt);
changeInt(srcInt);
print("int: " + srcInt);
//Test 3
ObjTest srcObj = new ObjTest();
srcObj.setInt(15);
srcObj.setString("srcObjStr");
print(srcObj.toString());
changeObj(srcObj);
print(srcObj.toString());
//Test 4
StringBuilder srcSB = new StringBuilder("src");
print(srcSB.toString());
changeSB(srcSB);
print(srcSB.toString());
}
public static void changeSB(StringBuilder decSB){
decSB.delete(0, decSB.length()).append("dec");
}
public static void changeStr(String decStr){
// decStr = new String("dec");
decStr = "dec";
}
public static void changeInt(int decInt){
decInt = 9;
}
/**
* Case1. new ObjectTest() is to change the direction of decObj.
* Case2. Only set properties for decObj is operating on the initial Object.
*/
public static void changeObj(ObjTest decObj){
// decObj = new ObjTest();
decObj.setInt(14);
decObj.setString("decObjStr");
}
public static void print(String str){
System.out.println(str);
}
}
输出结果:
src
src
int: 10
int: 10
The string is: srcObjStr, the int is: 15
The string is: decObjStr, the int is: 14
src
dec
对于上述测试,这里有一些说明:
Test 1 引用传递: 这是测试一个字符串【srcStr】传入方法【changeStr(String decStr)】后重新赋值【decStr = new String("dec")】,外面的字符串对象【srcStr】是否被改变? 答案是否。
srcStr 传给decStr其实传递的是引用,这个引用可以说是一个地址,指向都是同一个内存空间块(真正存储"src"的地方)。方法changeStr(String decStr)内,不管是通过new String("dec")赋值,还是通过 ="dec"赋值,Java虚拟机都是创建一个新的String对象,即开辟了一块新的内存空间,把地址赋给decSrc,这个时候,decSrc指向的就是新的对象了,所以跟外部的srcStr没有半毛钱关系。
Test 2 值传递:这是测试一个整型数值【srcInt】传入方法【changeInt(int decInt)】后重新赋值【decInt = 9】,外面的整型数值【srcInt】是否被改变?答案是否。
srcInt传递给decInt是一个值,但是,这是一个拷贝出来的值。srcInt和decInt分别代表了不同的内存块。所以传入方法后,不管怎么修改decInt,都改不了srcInt。
Test 3 引用传递:这是测试一个对象【srcObj】传入方法【changeObj(ObjTest decObj)】后重新赋值,外面的对象【srcObj】是否被改变?答案是如果创建新对象就否,如果直接修改就是。这个是为了跟Test 1做进一步分析。
srcObj传递给decSrc是一个引用,同Test 1。这次我们关注方法changeObj(ObjTest decObj)内部的不同实现所带来不同的结果:
* 如果内部有decObj = new ObjTest(),然后再对decObj进行操作,其实这个时候decObj指向的是新的对象,所以对新对象操作不会影响到srcObj所指向的对象。
* 如果内部没有decObj = new ObjTest(),而是直接对decObj进行操作,这个时候操作的就是srcObj所指向的对象,所以会影响到srcObj。
Test 4 引用传递:这是测试一个StringBuilder对象【srcSB】传入方法【changeSB(StringBuilder decSB)】后在原有空间赋值【decSB.delete(0, decSB.length()).append("dec")】,外面的StringBuilder对象是否被改变?答案是否。这是为了跟Test 1和Test 3做扩展分析。
原理都一样,对象传递的就是引用。
* 如果new StringBuilder()赋值给decSB的话,这就是一个新对象。不会改变外面的srcSB。
* 像测试方法里面的做法,就是为了在原有的空间操作字符串。自然会改变外面的srcSB。