zoukankan      html  css  js  c++  java
  • 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语言的这种指针的概念来实现的。

  • 相关阅读:
    容器占用空间的小问题
    一个ipv4到ipv6的移植问题
    一个linux内核模块移植到低版本时发生的异常
    一个发包乱序问题记录
    一个docker镜像中的目录删除不了问题
    C/C++(共用体与枚举)
    C/C++(数据结构栈的实现)
    C/C++(结构体)
    C/C++(内存管理)
    C/C++(指针数组)
  • 原文地址:https://www.cnblogs.com/simplykk/p/3745596.html
Copyright © 2011-2022 走看看