Java中值傳遞和引用傳遞的概念


很多書中都提到了在Java中只存在值傳遞,但是今天在一個NanoHTTPD的源碼中看到這樣一段:

 

1 if (qmi >= 0) {
2   decodeParms(uri.substring(qmi + 1), parms);
3   uri = decodePercent(uri.substring(0, qmi));
4 }
 1 /**
 2          * Decodes parameters in percent-encoded URI-format ( e.g.
 3          * "name=Jack%20Daniels&pass=Single%20Malt" ) and adds them to given
 4          * Map. NOTE: this doesn't support multiple identical keys due to the
 5          * simplicity of Map.
 6          */
 7         private void decodeParms(String parms, Map<String, String> p) {
 8             if (parms == null) {
 9                 p.put(QUERY_STRING_PARAMETER, "");
10                 return;
11             }
12 
13             p.put(QUERY_STRING_PARAMETER, parms);
14             StringTokenizer st = new StringTokenizer(parms, "&");
15             while (st.hasMoreTokens()) {
16                 String e = st.nextToken();
17                 int sep = e.indexOf('=');
18                 if (sep >= 0) {
19                     p.put(decodePercent(e.substring(0, sep)).trim(),
20                             decodePercent(e.substring(sep + 1)));
21                 } else {
22                     p.put(decodePercent(e).trim(), "");
23                 }
24             }
25         }

 

上面代碼是在調用decodeParms方法的時候傳入一個Map對象,該方法返回是void型,因此傳入的參數只能在方法內部修改,而不能返回,但是這段代碼很明顯是影響到對了方法外部的這個對象。這跟java中只有值傳遞的說法不一致,難道java中存在引用傳遞?

 

后來查閱文檔后發現,java中確實是只存在值傳遞。java中對象和基本類型的傳遞參數傳遞方式大不一樣,對於基本類型,java只是拷貝一個它本身的副本,而對象傳遞則是傳遞指向該對象的指針的值。

然而傳遞對象的指針的值並不代表是引用傳遞,看下面一段代碼:

 1 public class TestPassDemo {
 2     
 3     @Test
 4     public void  test() {
 5         TestPassDemo test = new TestPassDemo();
 6         Map<String, String> map1 = new HashMap<String, String>();
 7         map1.put("username", "David");
 8         Map<String, String> map2 = new HashMap<String, String>();
 9         map2.put("username", "Nick");
10         String user = "David";
11         int i = 1;
12         changeValue(map1,map2, user,i);
13         
14         //如果打印的是:{username=admin}則說明java的對象傳遞的是地址,如果是:{username=David}則傳遞的是值
15         System.out.println(map1);//{username=admin}
16         
17         System.out.println(map2);//{username=Nick}
18         //如果打印的是:admin則說明java的String對象傳遞的是地址,如果是:David則傳遞的是值
19         System.out.println(user);//David
20         System.out.println(i+"");//1
21     }
22     
23     public void changeValue(Map<String, String> map1,Map<String, String> map2, String str,int i){
24         map2 = map1;
25         map1.put("username", "Jack");
26         map2.put("username", "admin");
27         str = "admin";
28         i = 10;
29     }
30 
31 }

最后輸出的結果是這樣的:

{username=admin}
{username=Nick}
David
1

 

這說明了java中對象的傳遞只是一個指向該對象的指針的值,實際上也可以理解為一種值傳遞。

這就解釋了上面說的java中只存在值傳遞方法內部為何卻能改變外部的變量。

所謂java中的對象,實際上就是C語言中的指針的概念,本質上就是:在堆內存中開辟一塊空間,然后使用一個指針來引用它,舉一個例子來說的話:

 

一個Person對象是java中的一個對象,Person有name和age屬性,這時需要用一個指針來引用這個Person對象,Person對象又包含了對name對象和age對象的引用,所謂java的對象實際上也是利用C語言的這種指針的概念來實現的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM