1、String是属于值传递还是引用传递?
先看一段程序执行的样例:
public class test1 {
public static void main(String[] args) {
String str = "java";
nochange(str, str);
change(str, str);
}
public static void nochange(String str1,String str2) {
System.out.println("nochange--->>"+(str1 == str2));
}
public static void change(String str1,String str2) {
str1 = str1 + "";
System.out.println("change--->>"+(str1 == str2));
}
}
执行结果是:
nochange—>>true
change—>>false
可以据此看出String类型是引用传递,str1在执行+=操作时已经新New出了一个String类型的数据,这符号引用传递的特性。
2、但是String是特殊的引用类型,而且和值传递很类似,为什么这么说呢?
再看一段程序样例:
public class test2 {
public static void main(String[] args) {
test2 StringAsParamOfMethodDemo = new test2();
StringAsParamOfMethodDemo.testA();
}
private void testA() {
String originalStr = "original";
System.out.println("Test A Begin:"); //提示TestA开始了
System.out.println("The outer String: " + originalStr); //输出originalStr
simpleChangeString(originalStr); //执行方法,把originalStr传递过去,并改变该String型数据的值
System.out.println("The outer String after inner change: " + originalStr); //再次输出
System.out.println("Test A End.");
System.out.println();
}
public void simpleChangeString(String original) {
original = original + " is changed!";
System.out.println("The changed inner String: " + original);
}
}
执行结果:
Test A Begin:
The outer String: original
The changed inner String: original is changed!
The outer String after inner change: original
Test A End.
整段代码做的工作是先赋值一个String类型的局部变量,然后把这个变量作为参数送进一个方法中,在这个方法中改变该变量的值。
结果表明在方法内部对String类型的变量的重新赋值操作并没有对这个变量的原型产生任何影响。
我们知道在JAVA中,当传入的参数是基本类型时,方法操作的是参数变量(也就是原型变量的一个值的拷贝),改变的也只是原型变量的一个拷贝而已,而非变量本身。所以变量原型并不会随之改变。
但当方法传入的参数为非基本类型时(也就是说是一个对象类型的变量), 方法改变参数变量的同时变量原型也会随之改变。
String在这里体现的正是值传递的特性。
3、为什么会出现这样的悖论呢?
其实,要想真正理解一个类或者一个API/框架的最直接的方法就是看源码。
下面我们来看看new出String对象的那小段代码(String类中),也就是String类的构造函数:
public String(String original) {
int size = original.count;
char[] originalValue = original.value;
char[] v;
if (originalValue.length > size) {
// The array representing the String is bigger than the new
// String itself. Perhaps this constructor is being called
// in order to trim the baggage, so make a copy of the array.
int off = original.offset;
v = Arrays.copyOfRange(originalValue, off, off+size);
} else {
// The array representing the String is the same
// size as the String, so no point in making a copy.
v = originalValue;
}
this.offset = 0;
this.count = size;
this.value = v;
}
也许你注意到了里面的char[],这说明对String的存储实际上通过char[]来实现的。怎么样?其实就是一层窗户纸。不知道大家还记不记得在Java API中定义的那些基本类型的包装类。
比如Integer是int包装类、Float是float的包装类等等。对这些包装类的值操作实际上都是通过对其对应的基本类型操作而实现的。是不是有所感悟了?对,String就相当于是char[]的包装类。
包装类的特质之一就是在对其值进行操作时会体现出其对应的基本类型的性质。在参数传递时,包装类就是如此体现的。所以,对于String在这种情况下的展现结果的解释就自然而然得出了。
同样的,Integer、Float等这些包装类和String在这种情况下的表现是相同的,具体的分析在这里就省略了。
最后总结一下:
1、String是引用传递
2、String的参数传递具有值传递的特性,且这种特性是因为它是char[]的包装类
大部分内容转自
http://www.360doc.com/content/15/0810/15/20637232_490748261.shtml