今天,我在一本面试书上看到了关于java的一个参数传递的问题:

原文地址:http://guhanjie.iteye.com/blog/1683637

写道
java中对象作为参数传递给一个方法,到底是值传递,还是引用传递?

我毫无疑问的回答:“引用传递!”,并且还觉得自己对java的这一特性很是熟悉!

结果发现,我错了!

答案是:

值传递!Java中只有按值传递,没有按引用传递!

回家后我就迫不及待地查询了这个问题,觉得自己对java这么基础的问题都搞错实在太丢人!

综合网上的描述,我大概了解了是怎么回事,现在整理如下,如有不对之处望大神提出!

先来看一个作为程序员都熟悉的值传递的例子:

Java代码  
  1. ... ...
  2. //定义了一个改变参数值的函数
  3. public static void changeValue(int x) {
  4. x = x *2;
  5. }
  6. ... ...
  7. //调用该函数
  8. int num = 5;
  9. System.out.println(num);
  10. changeValue(num);
  11. System.out.println(num);
  12. ... ...

答案显而易见,调用函数changeValue()前后num的值都没有改变。

由此做一个引子,我用图表描绘一个值传递的过程:

num作为参数传递给changeValue()方法时,是将内存空间中num所指向的那个存储单元中存放的值,即"5",传送给了changeValue()方法中的x变量,而这个x变量也在内存空间中分配了一个存储单元,这个时候,就把num的值5传送给了这个存储单元中。此后,在changeValue()方法中对x的一切操作都是针对x所指向的这个存储单元,与num所指向的那个存储单元没有关系了!

自然,在函数调用之后,num所指向的存储单元的值还是没有发生变化,这就是所谓的“值传递”!值传递的精髓是:传递的是存储单元中的内容,而非地址或者引用!

接下来,就来看java中的对象参数是怎么传递的:

同样,先给出一段代码:

Java代码  
  1. ... ...
  2. class person {
  3. public static String name = "Jack";
  4. ... ...
  5. }
  6. ... ...
  7. //定义一个改变对象属性的方法
  8. public static void changeName(Person p) {
  9. p.name = "Rose";
  10. }
  11. ... ...
  12. public static void main(String[] args) {
  13. //定义一个Person对象,person是这个对象的引用
  14. Person person = new Person();
  15. //先显示这个对象的name属性
  16. System.out.println(person.name);
  17. //调用changeName(Person p)方法
  18. changeName(person);
  19. //再显示这个对象的name属性,看是否发生了变化
  20. System.out.println(person.name);
  21. }

答案应该大家都心知肚明:

第一次显示:“Jack”

第二次显示:“Rose”

方法用了一个对象参数,该对象内部的内容就可以改变,我之前一直认为应该是该对象复制了一个引用副本给调用函数的参数,使得该方法可以对这个对象进行操作,其实是错了!

http://www.cnblogs.com/clara/archive/2011/09/17/2179493.html 写道
Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是该对象的引用一个副本。指向同一个对象,对象的内容可以在被调用的方法中改变,但对象的引用(不是引用的副本)是永远不会改变的。 

为什么这里是“值传递”,而不是“引用传递”?

我还是用图表描绘比较能解释清楚:

主函数中new 了一个对象Person,实际分配了两个对象:新创建的Person类的实体对象,和指向该对象的引用变量person。

【注意:在java中,新创建的实体对象在堆内存中开辟空间,而引用变量在栈内存中开辟空间】

正如如上图所示,左侧是堆空间,用来分配内存给新创建的实体对象,红色框是新建的Person类的实体对象,000012是该实体对象的起始地址;而右侧是栈空间,用来给引用变量和一些临时变量分配内存,新实体对象的引用person就在其中,可以看到它的存储单元的内容是000012,记录的正是新建Person类实体对象的起始地址,也就是说它指向该实体对象。

这时候,好戏上台了:

调用了changeName()方法,person作为对象参数传入该方法,但是大家特别注意,它传入的是什么!!!person引用变量将自己的存储单元的内容传给了changeName()方法的p变量!也就是将实体对象的地址传给了p变量,从此,在changeName()方法中对p的一切操作都是针对p所指向的这个存储单元,与person引用变量所指向的那个存储单元再没有关系了!

回顾一下上面的一个值传递的例子,值传递,就是将存储单元中的内容传给调用函数中的那个参数,这里是不是异曲同工,是所谓“值传递”,而非“引用传递”!!!

那为什么对象内部能够发生变化呢?

那是因为:p所指向的那个存储单元中的内容是实体对象的地址,使得p也指向了该实体对象,所以才能改变对象内部的属性!

这也是我们大多数人会误以为是“引用传递”的终极原因!!!

Java中只有按值传递,没有按引用传递!相关推荐

  1. JAVA中的按值传递

    Java中只有按值传递,没有按引用传递! 方法参数共有两种类型: 基本数据类型 对象引用 一:基本数据类型 首先看一个小例子: 1 package chuandi; 2 3 public class ...

  2. java中是值传递引用传递_Java是按值传递而不是按引用传递

    java中是值传递引用传递 One of the biggest confusion in Java programming language is whether java is Pass by V ...

  3. Java:按值传递还是按引用传递详细解说

     Java:按值传递还是按引用传递详细解说 2012-11-14 23:02 44567人阅读 评论(17) 收藏 举报 本文章已收录于: 分类: java(48) 作者同类文章X 变量(6) 作 ...

  4. JAVA中参数传递问题的总结(按值传递和引用传递)

    关于JAVA中参数传递问题有两种,一种是按值传递(如果是基本类型),另一种是按引用传递(如果是對象). 首先以两个例子开始: 1) public class Test2 { public static ...

  5. Java 必知必会——什么是对象引用?按值传递 OR 按引用传递?

    1. 什么是对象? 任何事物都可以作为一个对象,一台电脑.一部手机等等等等. 在面向对象程序设计的 Java 中,程序是由对象组成的,对象包含了描述其状态的数据(属性)和可以执行的操作(方法),因此, ...

  6. 关于按值传递和按引用传递(送给这个方面的新手——包括我自己)

    我记得刚上大学我们学院就给我们开了第一门专业课--高级语言程序设计.在函数一节里面,首先要学到形式参数和实际参数,然后就学了按值传递和按引用传递,当时学得那叫一个云里雾里啊,再加上后面还学了个指针,弄 ...

  7. Java里的按值传递与引用传递

    按值传递还是按引用传递 这个在Java里面是经常被提起的问题,也有一些争论,似乎最后还有一个所谓的结论:"在Java里面参数传递都是按值传递".事实上,这很容易让人迷惑,下面先分别 ...

  8. java 中对象引用,以及对象赋值

    Java对象及其引用 Java对象及引用是容易混淆却又必须掌握的基础知识,本章阐述Java对象和引用的概念,以及与其密切相关的参数传递. 在许多Java书中,把对象和对象的引用混为一谈.可是,如果我分 ...

  9. Java中的参数传递 --Java

    1.基本类型传值,对象类型传地址 按值传递:当将一个参数传递给一个方法时,方法接收的是原始值的一个副本.因此,如果方法修改了该参数,仅改变副本,而原始值保持不变. 按引用传递:当将一个参数传递给一个方 ...

最新文章

  1. Unity3D 游戏引擎之平面小球重力感应详解【转】
  2. Android开发之使用TabLayout快速实现选项卡切换功能(附源码下载)
  3. directoryinfo 读取 映射磁盘_LoaRunner性能测试系统学习教程:磁盘监控(5)
  4. 项目实战中如何使用抽象类和接口
  5. python获取路径下所有文件_Python获取路径下所有文件名
  6. oracle数据管理员常用词语,总结Oracle数据库管理员的常用命令
  7. 解决实例化Servlet类[com.mu.servlet.HelloServlet]异常
  8. 在运行 Red Hat 或 Cent OS 的虚拟机中扩展逻辑卷
  9. Linux----Ubuntu系统官网下载iso镜像文件
  10. 计算几何03_三次参数样条曲线与Cardinal曲线
  11. 520,冰河亲自整理的Git命令汇总升级版,悄悄努力,然后惊艳所有人(升级版)
  12. 算法设计与分析: 6-8 圆排列问题
  13. 分享四种将PDF文件转换为CAD文件的方法,总有一个方法适合你
  14. LimeSDR-USB 初学者教程(Windows)
  15. 多级反馈队列调度算法(c++)
  16. difference()、differenceBy()、differenceWith()
  17. 四川广电网络、阿里云、数梦工场强强联手 共建“智慧广电城市大脑”
  18. 写好一份软件开发设计文档
  19. C++标准程序库(学习笔记)二
  20. HUAWEI Mate 40 Pro 详细配置

热门文章

  1. leetcode 之Remove Nth Node From End of List(19)
  2. as与c++的反射机制对比
  3. winform技巧一,errorprovider,任务栏可见,总在最前
  4. Defect Prevention - How to prevent defect in process!
  5. 由作用域安全的构造函数想到的
  6. const在c中的用法
  7. C#微信开发小白成长教程二(新手接入指南,附视频)
  8. Linux 上网配置 修改IP
  9. WCF:Maximum number of items that can be serialized or deserialized in an object graph is '65536'.
  10. Java,想说爱你真不容易