JAVA 值传递与引用传递详解

今晚在某QQ群上看见有讨论该问题,于是想做个MARK。

一般性:

大家都知道,在JAVA中变量有以下两种:

基本类型变量,包括char、byte、short、int、long、float、double、boolean。
引用类型变量,包括类、接口、数组(基本类型数组和对象数组)。

 

对于基本类型的变量:

值传递,在调用方法时传给方法一个参数的拷贝值(这个值就是value),所以方法体内部使用的参数只是一个“附件”。它与原参数没有关系,在方法体内部中,该值的改变也不会影响原参数。

对于引用(这里改称指针更形象)类型的变量:

引用传递,在调用方法时传给方法一个参数引用(这个值就是指针地址)的拷贝,(所以也有人支持这里也是值传递,传递的是地址值)。可以打个比喻:我熊猫有一张藏宝图指向一堆宝藏(指针指向对象),我派佣人去取宝藏(调用方法),我就复印了一份藏宝图交给佣人(拷贝指针作为参数传递给被调用的方法)。佣人根据藏宝图找到宝藏并变卖了一部份宝藏(在方法内部通过拷贝的指针改变了对象的值)。现在我手上的这份藏宝图指向的宝藏的数量是否被改变了?所以,引用传递是会改变原值的。

 

特殊性:

问:String  是值传递还是引用传递? 为什么值不会改变?那String[]呢?StringBuffer呢?

答:String是"类似值传递"、String数组是引用传递。

 

public class TestString{

     public static void main(String args[]){

         String strTest=new String("ab");

         //String strTest="ab";这两种形式的定义,输出的都是ab

         setString(strTest);

         System.out.println(strTest);

     }

     private static void setString(String str){

         str=str+"c";

    }

 }

解析:对于java初学者来说,很多人在执行程序以前一定认为输出的将会是"abc”,但是结果告诉我们输出的会是"ab",这就是String的“类似值传递”(即可以将String看做int,double等基本类型,这些基本类型作为参数是值传递,但String在java规范中又不是基本类型,所以此处称其为“类似值传递”)。在java中是将String看做引用类型的,既然如此,那此处到底是不是引用传递呢?可以明确的告诉大家,这里绝对是引用传递。那既然是引用传递,为什么却时值传递的效果呢?答案其实已经在开篇告诉大家了:java语言规范规定,String型变量指向的内存空间中的内容是不能被改变的。下面来详细解析一下,当我们刚开始调用setString()函数的时候,strTest和str同时指向了"ab”所在的内存单元,然后在setString()中试图改变str的值,根据String的不可改变性,此时系统会分配新的内存并令str指向该内存,该内存的内容为abc;而对于strTest他仍然指向原来的内存单元----即ab所在的内存单元,此处和示例二的道理相同。到这里读者应该明白原因了吧,其实仍然是引用传递,只不过由于String的不可变的性质,导致String变量作为参数的特殊性。

StringBuffer不特殊

StringBuffer 跟其他对象一样,属于引用传递。为什么呢?根据上面的分析可以看出String与StringBuffer时相反的。StringBuffer是可变字符串对象。就是说您可以根据藏宝图改变宝藏(对象)。有另外一种情况容易混淆:有时候传过去的拷贝指针被重新赋值了!也就是说地址值被改变了!复印给佣人的藏宝图被掉包了!它指向的是一堆石头!这种情况下原来主人手里的地图指向的宝藏对象是没有被改变的。可以仔细查看我下面的小例子,右边有每一步打印的结果。

/**
 * @author F|sh_cx
 */
public class CX2 {
 public static void test(StringBuffer a,StringBuffer b){
  a.append(b);
     System.out.println("a.hashCode="+a.hashCode());//(2) a.hashCode=3526198
     System.out.println("a="+a);//(3) a=AB
     System.out.println("b.hashCode="+b.hashCode());//(4) b.hashCode=7699183
  b = a; 
  System.out.println("b.hashCode="+b.hashCode());//(5) b.hashCode=3526198
 }
 public static void main(String[] args) {
  StringBuffer a = new StringBuffer("A");
  System.out.println(a.hashCode());//(1)3526198
  StringBuffer b = new StringBuffer("B");
  test(a,b);
  System.out.println(a.hashCode()+","+b.hashCode());//(6) 3526198,7699183
  System.out.println("a:"+a);//(7) a:AB
  System.out.println("b:"+b);//(8) b:B 
 }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值