staticvoid change(String str,finalchar[] a){
str = "change";
System.out.println(str.hashCode());
a[0] = 'A';
}
publicstaticvoid main(String[] args) {
String str = "Hello";
System.out.println(str.hashCode());
finalchar[] array = {'a','b','c','d'};
change(str,array);
System.out.println(str.hashCode());
System.out.println(str);
System.out.println(array);
}




这说明对String的存储实际上通过char[]来实现的。怎么样?其实就是一层窗户纸。不知道大家还记不记得在Java API中定义的那些基本类型的包装类。比如Integer是int包装类、Float是float的包装类等等。对这些包装类的值操作实际上都是通过对其对应的基本类型操作而实现的。是不是有所感悟了?对,String就相当于是char[]的包装类。包装类的特质之一就是在对其值进行操作时会体现出其对应的基本类型的性质。在参数传递时,包装类就是如此体现的。所以,对于String在这种情况下的展现结果的解释就自然而然得出了。同样的,Integer、Float等这些包装类和String在这种情况下的表现是相同的,具体的分析在这里就省略了,有兴趣的朋友可以自己做做试验。
这也就是为什么若组串操作是通过不同方法来实现的时候,推荐大家使用StringBuffer的真正原因了。至于StringBuffer为什么不会表现出String这种现象,大家再看看的StringBuffer的实现就会明白了,在此也不再赘述了。



 



note: 关键在于在调用的方法中如果我们使用new去重新给形参对象分配新的内存地址,那没这个形参的地址就变了,然后再对该对象做任何修改都不会影响到原来的对象。



而string在调用的方法中用‘=’赋值,相当于指定了一个新的引用给它,因为字符串常量“”是一个新的引用。



 




package net.xxt; 
   

 /** 
   
 * 测试JAVA参数传递是值传递还是引用传递 
   
 * @author   zhaoguoli 
   
 * @version  v1.0 2009-07-02 晚11点 create 
   
 */ 
   
 public class ParamPass { 
   

 /* 
   
 * 8个基本类型 ,传值-----不改变 
   
 */ 
   
 public void change(int a){ 
   
 a = 5; 
   
 } 
   

 /* 
   
 * 类,传值,但值是内存中一个对象的地址-----改变 
   
 */ 
   
 public void change(Person p){ 
   
 p.age = 22; 
   
 p.sex = 1; 
   

 } 
   

 /* 
   
 * 类,传值,但字符串是常量,一旦赋值就不会改变 -----不变 
   
 */ 
   
 public void change(String str){ 
   
 str = "123"; 
   
 } 
   


 /* 
   
 * 数组是对象,传值------改变 
   
 */ 
   
 public void change(int[] array){ 
   
 for (int i = 0; i < array.length; i++) { 
   
 array[i] = i; 
   
 } 
   
 } 
   


 /** 
   
 * @param args 
   
 */ 
   
 public static void main(String[] args) { 
   
 // TODO Auto-generated method stub 
   


 ParamPass test = new ParamPass(); 
   
 /* 
   
 * 原生数据类型 
   
 * 在栈中分配内存,存放a = 1 
   
 * 在参数传递中,将1赋于了另外一个栈中的变量(形参),两者互不影响 
   
 */ 
   
 int a = 1; 
   
 test.change(a); 
   
 System.out.println(a); 
   

 /* 
   
 * 类对象Person 
   
 * 先在堆中分配空间,调用构造函数 
   
 * 然后将堆中的分配空间的首地址赋于栈中的P 
   
 * 在参数传递中,将栈中P的值,也就是堆中分配空间的首地址赋于另外一个栈中的变量(形参) 
   
 * 由于两者指向同一个地址,所以两者互相影响 
   
 */ 
   
 Person p = new Person(12,11); 
   
 test.change(p); 
   
 System.out.println(p.age); 
   
 System.out.println(p.sex); 
   

 /* 
   
 * 字符串"abc"在堆中分配空间 
   
 * 然后将堆中的分配空间的首地址赋于栈中的str 
   
 * 在参数传递中,将栈中str的值,也就是堆中分配空间的首地址赋于另外一个栈中的变量(形参str) 
   
 * 在方法中:(形参str)重新执行了上面三步:即(形参str)指向了堆中的另外一个首地址,两者指向的已经不是同一个地址 
   
 * 所以两者互不影响 
   
 */ 
   
 String str = "abc"; 
   
 test.change(str); 
   
 System.out.println(str); 
   

 /* 
   
 * 数组的分析相对比较复杂:相当于一个容器,可参考Person 
   
 */ 
   
 int[] array = {9,8,7,6,5,4,3,2,1}; 
   
 // int[] arr = new int[9];   // 从new 可以看出是在堆中 
   
 // for (int i = 0; i < arr.length; i++) { 
   
 // arr[i] = 9 - i; 
   
 // } 
   
 // System.out.println(arr.toString()); 
   

 test.change(array); 
   
 for (int i = 0; i < array.length; i++) { 
   
 System.out.println(array[i]); 
   
 } 
   

 } 
   

 } 
   

 class Person { 
   
 int age ; 
   
 int sex; 
   
 public Person(int age, int sex) { 
   
 this.age = age; 
   
 this.sex = sex; 
   
 } 
   

 } 
   
 // 
   
 //输出结果为: 
   
 //1 
   
 //22 
   
 //1 
   
 //abc 
   
 //0 
   
 //1 
   
 //2 
   
 //3 
   
 //4 
   
 //5 
   
 //6 
   
 //7 
   
 //8 
   
 // 
   
 //结论: 
   
 //1.java 方法参数传递一律是传值 
   
 //2.字符串是常量,一量更改就不能再改变其值 
   
 //3.数组是对象