JAVA引用COPY传递

 

在面试过程中被问到:在Java中是值传递,还是引用传递。当时只知道java在传递基本数据类型时传递的是值,在传递对象是是传递的引用。其实java中只有值传递。

 

 Java  应用程序中永远不会传递对象,而只传递对象引用。因此是按引用传递对象。但重要的是要区分参数是如何传递的,这才是该节选的意图。 Java  应用程序按引用传递对象这一事实并不意味着  Java  应用程序按引用传递参数。参数可以是对象引用,而  Java  应用程序是按值传递对象引用的。
Java  应用程序中的变量可以为以下两种类型之一:引用类型或基本类型。当作为参数传递给一个方法时,处理这两种类型的方式是相同的。两种类型都是按值传递的;没有一种按引用传递。
按值传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的一个副本。因此,如果函数修改了该参数,仅改变副本,而原始值保持不变。按引用传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的内存地址,而不是值的副本。因此,如果函数修改了该参数,调用代码中的原始值也随之改变。
当传递给函数的参数不是引用时,传递的都是该值的一个副本(按值传递)。区别在于引用。在  C++  中当传递给函数的参数是引用时,您传递的就是这个引用,或者内存地址(按引用传递)。  Java  应用程序中,当对象引用是传递给方法的一个参数时,您传递的是该引用的一个副本(按值传递),而不是引用本身。

 

下面这个blog感觉写的还不错!

 

对于Java的值传递, 你真的了解么? Java里面只有值传递, 这个值是什么? 如果是基本数据类型。  你也许回答的很干脆。 但如果是Object对象呢? 你确定清楚不? 先看下code。

  1. package com.basic;     
  2.     
  3. public class Test {     
  4.     
  5.     /**   
  6.      * @param args   
  7.      */    
  8.     public static void main(String[] args) {         
  9.         StringBuffer buffer= new StringBuffer("colin");     
  10.         SChange(buffer);     
  11.         System.out.println( buffer);     
  12.     }     
  13.          
  14.     public static void SChange (StringBuffer str) {     
  15.         str= new StringBuffer("huang");     
  16.     }     
  17.     
  18. }    

上面code, 输出的结果是什么? 你对了吗?

输出的结果是 colin.

我们修改下code

  1. package com.basic;     
  2.     
  3. public class Test {     
  4.     
  5.     /**   
  6.      * @param args   
  7.      */    
  8.     public static void main(String[] args) {         
  9.         StringBuffer buffer= new StringBuffer("colin");     
  10.         SChange(buffer);     
  11.         System.out.println( buffer);     
  12.     }     
  13.          
  14.     public static void SChange (StringBuffer str) {     
  15.         //str= new StringBuffer("huang");      
  16.         str.append(" huang");     
  17.     }     
  18.     
  19. }    

输出的结果是 colin huang.

为什么是这样的结果呢?  下面详细解释:

Java确实通过引用来维护Object, 所有的Object变量, 都是一个引用。但Java在方法传递中, 确实是值传递。  那这个值是什么呢。 对于Object, 这个值就是传人的Object的引用。既把这个引用copy了一份。 那么, 就至少有两个引用指向了这同一个传入的Object。 参考下图:

那么, 我们就来图解下上面的那两个代码。

下图图解代码一

接着图解代码二

代码一中, copy的那个引用, 指向了一个新的对象。 但原对象还是没有变化的。
代码二中, copy的那个引用, 把原对象改变了。


这就是Java的值传递。

 

 

Java  应用程序按值传递所有参数,这样就制作所有参数的副本,而不管它们的类型。

  1. class Test  
  2. {  
  3.   public static void main(String args[])  
  4.   {  
  5.     int val;  
  6.     StringBuffer sb1, sb2;  
  7.    
  8.     val = 10;  
  9.     sb1 = new StringBuffer("apples");  
  10.     sb2 = new StringBuffer("pears");  
  11.     System.out.println("val is " + val);  
  12.     System.out.println("sb1 is " + sb1);  
  13.     System.out.println("sb2 is " + sb2);  
  14.     System.out.println("");  
  15.    
  16.     System.out.println("calling modify");  
  17.     //按值传递所有参数   
  18.     modify(val, sb1, sb2);  
  19.     System.out.println("returned from modify");  
  20.     System.out.println("");  
  21.    
  22.     System.out.println("val is " + val);  
  23.     System.out.println("sb1 is " + sb1);  
  24.     System.out.println("sb2 is " + sb2);  
  25.   }  
  26.    
  27.   public static void modify(int a, StringBuffer r1,  
  28.                             StringBuffer r2)  
  29.   {  
  30.       System.out.println("in modify...");  
  31.       a = 0;  
  32.       r1 = null;  //1   
  33.       r2.append(" taste good");  
  34.       System.out.println("a is " + a);  
  35.       System.out.println("r1 is " + r1);  
  36.       System.out.println("r2 is " + r2);  
  37.   }  
  38. }  
  

Java  应用程序的输出
  1.  
  2. val is 10
  3. sb1 is apples
  4. sb2 is pears
  5.  
  6. calling modify
  7. in modify...
  8. a is 0
  9. r1 is null
  10. r2 is pears taste good
  11. returned from modify
  12.  
  13. val is 10
  14. sb1 is apples
  15. sb2 is pears taste good
  16.  


这段代码声明了三个变量:一个整型变量和两个对象引用。设置了每个变量的初始值并将它们打印出来。然后将所有三个变量作为参数传递给  modify  方法。

modify 
方法更改了所有三个参数的值:  

将第一个参数(整数)设置为  0  
将第一个对象引用  r1  设置为  null  
保留第二个引用  r2  的值,但通过调用  append  方法更改它所引用的对象(这与前面的  C++  示例中对指针  p  的处理类似)。

当执行返回到  main  时,再次打印出这三个参数的值。正如预期的那样,整型的  val  没有改变。对象引用  sb1  也没有改变。如果  sb1  是按引用传递的,正如许多人声称的那样,它将为  null 。但是,因为  Java  编程语言按值传递所有参数,所以是将  sb1  的引用的一个副本传递给了  modify  方法。  modify  方法在  //1  位置将  r1  设置为  null  时,它只是对  sb1  的引用的一个副本进行了该操作,而不是像  C++  中那样对原始值进行操作。

另外请注意,第二个对象引用  sb2  打印出的是在  modify  方法中设置的新字符串。即使  modify  中的变量  r2  只是引用  sb2  的一个副本,但它们指向同一个对象。因此,对复制的引用所调用的方法更改的是同一个对象。

 

Java 应用程序按值传递所有参数,这样就制作所有参数的副本,而不管它们的类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值