很多书中都提到了在Java中只存在值传递,但是今天在一个NanoHTTPD的源码中看到这样一段:

 if (qmi >= 0) {
  decodeParms(uri.substring(qmi + 1), parms);
3   uri = decodePercent(uri.substring(0, qmi));
}
 /**
* Decodes parameters in percent-encoded URI-format ( e.g.
* "name=Jack%20Daniels&pass=Single%20Malt" ) and adds them to given
* Map. NOTE: this doesn't support multiple identical keys due to the
* simplicity of Map.
*/
private void decodeParms(String parms, Map<String, String> p) {
if (parms == null) {
p.put(QUERY_STRING_PARAMETER, "");
return;
} p.put(QUERY_STRING_PARAMETER, parms);
StringTokenizer st = new StringTokenizer(parms, "&");
while (st.hasMoreTokens()) {
String e = st.nextToken();
int sep = e.indexOf('=');
if (sep >= 0) {
p.put(decodePercent(e.substring(0, sep)).trim(),
decodePercent(e.substring(sep + 1)));
} else {
p.put(decodePercent(e).trim(), "");
}
}
}

上面代码是在调用decodeParms方法的时候传入一个Map对象,该方法返回是void型,因此传入的参数只能在方法内部修改,而不能返回,但是这段代码很明显是影响到对了方法外部的这个对象。这跟java中只有值传递的说法不一致,难道java中存在引用传递?

后来查阅文档后发现,java中确实是只存在值传递。java中对象和基本类型的传递参数传递方式大不一样,对于基本类型,java只是拷贝一个它本身的副本,而对象传递则是传递指向该对象的指针的值。

然而传递对象的指针的值并不代表是引用传递,看下面一段代码:

 public class TestPassDemo {

     @Test
public void test() {
TestPassDemo test = new TestPassDemo();
Map<String, String> map1 = new HashMap<String, String>();
map1.put("username", "David");
Map<String, String> map2 = new HashMap<String, String>();
map2.put("username", "Nick");
String user = "David";
int i = 1;
changeValue(map1,map2, user,i); //如果打印的是:{username=admin}则说明java的对象传递的是地址,如果是:{username=David}则传递的是值
System.out.println(map1);//{username=admin} System.out.println(map2);//{username=Nick}
//如果打印的是:admin则说明java的String对象传递的是地址,如果是:David则传递的是值
System.out.println(user);//David
System.out.println(i+"");//
} public void changeValue(Map<String, String> map1,Map<String, String> map2, String str,int i){
map2 = map1;
map1.put("username", "Jack");
map2.put("username", "admin");
str = "admin";
i = 10;
} }

最后输出的结果是这样的:

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

这说明了java中对象的传递只是一个指向该对象的指针的值,实际上也可以理解为一种值传递。

这就解释了上面说的java中只存在值传递方法内部为何却能改变外部的变量。

所谓java中的对象,实际上就是C语言中的指针的概念,本质上就是:在堆内存中开辟一块空间,然后使用一个指针来引用它,举一个例子来说的话:

一个Person对象是java中的一个对象,Person有name和age属性,这时需要用一个指针来引用这个Person对象,Person对象又包含了对name对象和age对象的引用,所谓java的对象实际上也是利用C语言的这种指针的概念来实现的。

Java中值传递和引用传递的概念的更多相关文章

  1. 在Java中字符串是通过引用传递的?

    这是一个经典的java问题.在stackoverflow上,许多类似的问题已经被问过了,但是许多回答是错误的或不完整的. 如果你不想深入思考的话,这个问题很简单.如果你想明白的更彻底,那么问题可能容易 ...

  2. 多图证明,Java到底是值传递还是引用传递?

    开篇先来曝答案,在 Java 语言中,本质只有值传递,而无引用传递,解释和证明详见正文. 说到值传递和引用传递我们不得不提到两个概念:值类型和引用类型. 1.值类型 通俗意义上来说,所谓的值类型指的就 ...

  3. Java中引用类型变量,对象,值类型,值传递,引用传递 区别与定义

    一.Java中什么叫做引用类型变量?引用:就是按内存地址查询       比如:String s = new String();这个其实是在栈内存里分配一块内存空间为s,在堆内存里new了一个Stri ...

  4. java中值传递和引用传递

    最近工作中使用到了值传递和引用传递,但是有点懵,现在看了下面的文章后清晰多了.一下是文章(网摘) 1:按值传递是什么 指的是在方法调用时,传递的参数是按值的拷贝传递.示例如下: public clas ...

  5. Java中的值传递和引用传递

    这几天一直再纠结这个问题,今天看了这篇文章有点思路了,这跟C++里函数参数为引用.指针还是有很大区别. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里 ...

  6. java中方法的参数传递机制(值传递还是引用传递)

    看到一个java面试题: 问:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?  答:是值传递.Java 编程语言只有值传递参 ...

  7. 一道笔试题来理顺Java中的值传递和引用传递

      题目如下: private static void change(StringBuffer str11, StringBuffer str12) { str12 = str11; str11 = ...

  8. java中的值传递和引用传递有什么区别呀?

    值传递: (形式参数类型是基本数据类型和String):方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参 ...

  9. Java中的值传递与引用传递

    1.基本类型和引用类型在内存中的保存 Java中数据类型分为两大类,基本类型和对象类型.相应的,变量也有两种类型:基本类型和引用类型. 基本类型的变量保存原始值,即它代表的值就是数值本身: 而引用类型 ...

  10. java中参数传递--值传递,引用传递

    java中的参数传递——值传递.引用传递   参数是按值而不是按引用传递的说明 Java 应用程序有且仅有的一种参数传递机制,即按值传递. 在 Java 应用程序中永远不会传递对象,而只传递对象引用. ...

随机推荐

  1. mysql基础安全

  2. Bash:-:-通过while和shift判断脚本位置参数格式是否合法

    ]];then echo "请输入2个位置参数..." exit else num=$# ));do case ${num} in ) if ! echo "${1}&q ...

  3. json pickle time

    多层装饰器: 字符串格式化: 当字符串格式化时 , %% 生成器 使用函数创造的 yield递归模块PY:模块其他:类库 先导入 后使用 自定义模块内置模块第三方模块为什么要有模块 将代码归类模块的内 ...

  4. 传感器之超声波测距HC-SR04

    一.前言 HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测距精度可达高到3mm:模块包括超声波发射器.接收器与控制电路.像智能小车的测距以及转向,或是一些项目中,常常会用 ...

  5. android 命令行

    android create avd --target --name cupcake 建立模拟器:           $ android create avd --target 2 --name c ...

  6. WinSCP无法连接 ubuntu 的解决方法

    ubuntu默认不安装sshd服务 需要sudo apt-get install ssh 你可以在ubuntu本机ssh localhost测试是否成功安装了ssh 因为WinSCP是基于ssh的sf ...

  7. C#常用开源类库

    一.AOP框架        Encase 是C#编写开发的为.NET平台提供的AOP框架.Encase 独特的提供了把方面(aspects)部署到运行时代码,而其它AOP框架依赖配置文件的方式.这种 ...

  8. Boost学习笔记(二) 时间与日期

    timer库概述 timer库包含三个组件:分别是计时器类timer.progress_timer和进度指示类progress_display timer 主要作用是计时,精确度是毫秒级.下面是一个简 ...

  9. [CF752D]Santa Claus and a Palindrome(优先队列,贪心乱搞)

    题目链接:http://codeforces.com/contest/752/problem/D 题意:给长度为k的n个字符串,每一个字符串有权值,求构造一个大回文串.使得权值最大. 因为字符串长度都 ...

  10. JS事件模型小结

    三种事件模型:原始事件模型(DOM0),DOM2事件模型,IE事件模型: 不同点: 事件程序的注册(给HTML元素所对应的JS对象绑定事件) 事件传播的过程 事件模型的注册: 一.原始事件模型(没有兼 ...