public static void main(String[] args) {
StringAsParamOfMethodDemo StringAsParamOfMethodDemo =
new StringAsParamOfMethodDemo();
StringAsParamOfMethodDemo.testA();
}
private void testA() {
String originalStr = "original";
System.out.println( "Test A Begin:");
System.out.println( "The outer String: " + originalStr);
simpleChangeString(originalStr);
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);
}
}
changeNumber(number) {number++}; //改变送进的int变量
System.out.println(number); //这时number依然为0
changeStringBuffer(strBuf) {strbuf.apend(“ is changed!”)} //改变送进的StringBuffer变量
System.out.println(strBuf); //这时strBuf的值就变为了original is changed!
String originalStr = new String("original");
System.out.println("Test B Begin:");
System.out.println("The outer String: " + originalStr);
changeNewString(originalStr);
System.out.println("The outer String after inner change: " + originalStr);
System.out.println("Test B End:");
System.out.println();
}
public void changeNewString(String original) {
original = new String(original + " is changed!");
System.out.println("The changed inner String: " + original);
}
String originalStr = new String( "original");
System.out.println( "Test C Begin:");
System.out.println( "The outer String: " + originalStr);
changeStrWithMethod(originalStr);
System.out.println( "The outer String after inner change: " + originalStr);
System.out.println( "Test C End.");
System.out.println();
}
private static void changeStrWithMethod(String original) {
original = original.concat( " is changed!");
System.out.println( "The changed inner 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;
}
有一道比较经典的java试题,有如下一个类,执行完main函数后,系统打印出的是什么:
public class Test1 {
private static String reverseString(String resource,String result){
for(int i=resource.length()-1;i>=0;i--){
result = result + resource.charAt(i);
}
return result;
}
public static void main(String args[]){
String s = "123456789";
String r = "abcdefg";
reverseString(s,r);
System.out.println(r);
}
}
答案是打印的是"abcdefg",也就是经过reverseString方法,result字符串的值没有变化,这是为什么呢?要回答这个问题就必须要解析java中的参数传递机制。
首先我们要明白以下三个问题:
1、java中基本类型变量的地址(指系统分配给该变量的物理地址,下同)中存放的是变量的值,比如int x=21;中x的地址中存放的是21。
2、java中对象类型(除基本类型)变量的地址中存放的并不是对象(指内容),而只是一个地址,对象实际分配的物理地址。举个例子,Test1 t = new Test1();中首先系统实例化Test1,分配一块物理地址存放Test1的实例,起始地址是ff0001,然后再分配一块物理地址给变量t,起始地址是ff0f28,而在这块地址中存放的是ff0001。
3、java对基本类型的参数是传值传递的,对对象类型的参数是引用传递的,String也不例外也是引用传递的。
分析:根据第3点,我们可以知道形参result的地址中存放的是实参r的地址中的内容,根据第2点,我们可以知道是"abcdefg"对象的起始物理地址,对形参result的第一个操作就是result = result + resource.charAt(i);,String类的+也就是contact方法返回的是一个new String,这点可以查看String的源代码,也就是说result的地址中的内容被修改为一个新的地址,即是new String对象的起始物理地址,这样result与r完全无关了,后面的所有对result的操作也就跟r完全无关了,所以r最后没有任何改变。
另一个非String的对象,其实参与形参无关的例子,最后打印结果是300:
public class Test5 {
private static InnClass reverseString(InnClass resource,InnClass result){
result = resource;
return result;
}
public static void main(String args[]){
Test5 t = new Test5();
Test5.InnClass iClass1 = t.new InnClass();
Test5.InnClass iClass2 = t.new InnClass();
iClass1.setA(100);
iClass2.setA(300);
reverseString(iClass1,iClass2);
System.out.println(iClass2.getA());
}
class InnClass{
int a=0;
void setA(int val){
a = val;
}
int getA(){
return a;
}
}
}
那如何才能通过对对象类型的形参的改变影响到实参呢?
考察下面的类的打印结果:
public class Test1 {
private static String reverseString(String resource,String result){
for(int i=resource.length()-1;i>=0;i--){
result = result + resource.charAt(i);
}
return result;
}
public static void main(String args[]){
String s = "123456789";
String r = "abcdefg";
r = reverseString(s,r);
System.out.println(r);
}
}
结论:java对于基本类型的参数以值传递的方式,对于非基本类型(对象类型)的参数以引用传递的方式,String作为对象类型在作为参数时以引用传递的方式。