参数传递是什么?
     在C的函数或是JAVA的方法中,向一个函数或方法内部传递一个参数,比如:
 
void fun( int num ){
    num+=2 ;
}
 
int a = 3 ;
fun( a ) ;
 
     这个a就被作为参数传入函数fun()中,作为a,然后返回或者不返回值
 
     回到最初,函数的作用是复用,那么我们希望这个参数传递是什么样的呢?就是假如我们去掉函数的外衣,就让函数变成代码放到之前是函数的地方,那么很自然这里最后b的值会被改变,这可以说是最朴实的参数传递了,自然的样子。
 
     但是人们又发明了另一种方式
     其实我认为这是人们重新定义函数,把函数只作为一段代码的复用上升到一个工具,函数不是作为调用函数代码的一部分,而是把函数作为一个工具,一个函数只能以返回值的方式影响调用代码(这里不考虑在函数体内能跟调用代码中除了参数以外的代码沟通,因为java中泛滥了,其实java中能取到的值也是类中的而不是调用代码的)的,这样更加安全。
     这种方式采用的方法是复制一个新值放到函数中去运算,就像:在调用时初始化的局部变量。我们知道局部变量的生存空间只有函数内,这样函数内部的操作就不会影响到外面。
     这种方式被称为值传递。 那它是怎么实现的呢?看下面。
 
上面说了复制一个新值,其实这个东西很有门道。
     先从硬件说起。
     所有的代码在跑的时候,里边数据都是放在内存中的,包括文件啊什么的都需要从硬盘啊SD卡中取出来,放到内存中,也就是说你所有的值啊,对象啊,都在内存中。
     而内存中放这些东西的地方分为两块:堆、栈
     很俗套的情节:其中栈的位置小,速度快,堆的位置大,速度慢
     于是很自然会有一套放东西的规划,小的数据,用的多的数据,放栈中,大的数据,用得少的数据,放堆中
 
     具体在JAVA中是这样的:
  • JAVA中所有的数据类型有9种,8种基本类型和1种对象类型,对象类型又分为系统自建和用户自建
  • int、long、double、float、byte、boolean、char 这七种基本类型的数据是直接放在栈中
  • string基本类型和所有的对象类型的数据(这里的数据指的是实例化的对象,空的类不是数据)放在堆中,在栈中存放在堆中的指针
 
     所以如果要说复制一个新值,对于只存在栈中和存放在在栈和堆中的数据来说,情况是不一样的。
     说复制之前,要说一下创建,创建一个值的时候发生了什么?同样是分两种情况:
  1. 创建一个存放在栈中的数据
    1. 比如:int a = 3 ; 这一句其实是两步:int a ; a = 3 ;
    2. 第一步 int a 是在栈中找了并且开辟了一个放int类型的存储空间,然后把这个存储空间跟变量名a绑定起来了(我自定义绑定的机制发生在命名空间中);
    3. 第二步是把3这个值存入a绑定的存储空间中。
  2. 创建一个 指针存放在栈中,内容存放在堆中 的数据
    1. 比如:Apple myapple = new Apple() ; 这一句也是两步:Apple myapple ; myapple = new RedApple() ;
    2. 第一步是在栈中找了并且开辟了一个存储空间,因为声明不是基本类型,所以它开辟了一个指针类型的存储空间,然后把这个存储空间跟对象名myapple绑定起来了;
    3. 第二步是(这里特意用了多态的属性)先在内存的堆中开辟一个能够存放RedApple对象的空间(这个空间没有绑定命名空间),然后经过类型检查是否合法之后,把这个空间的地址存放在跟myapple绑定的指针空间中
     数据在内存中的状态就像这样:
     
 
     好,回到开始,那么复制一个新值到函数中运算的复制的真实情况是什么样子?
     假如是这两个函数:
 
           
 
     传参的过程其实是一个赋值的过程:
  • fun(a); 这句执行的时候,传参其实是执行了这么两句:int num ; num = a ;
    • 在栈中开辟了一个int类型int大小空间,并且绑定num,然后把a绑定的栈空间中的数据复制一份放到num绑定的栈空间中
  • fun(myapple)这句执行的时候也是一样:Apple apple ; apple = myapple ;
    • 在栈中开辟了一个Apple类型指针大小空间,并且绑定apple,然后把myapple绑定的栈空间的数据(是地址啊)复制衣服放到apple绑定的栈空间中
现在数据在内存中的状态就像这样:
 
这种在传参时,把a绑定的栈空间中的数据复制一份放到num绑定的栈空间中 的行为就叫做值传递(同样发生在=运算符赋值运算符的时候)。
 
不过你要注意,你也能很清晰看到,所谓值传递之后,在函数中对变量进行操作会不会影响到调用函数代码中的变量,是不一定的,需要看传的是值还是地址,也就看真实数据是放在哪里,真实数据放在堆中传递的是栈中的地址时,就能被改变。
 
不过其实如果传入的时地址,能不能改变也要看是什么操作。
以上面的apple.dosomesth() 为例:
  • 假如这个方法能对apple的某些值进行操作,那么调用函数的代码中的myapple的内容也会受到改变
  • 但如果是赋值,也就是JAVA中的赋值。那么,它进行的还是值传递,受改变的是在局部变量中new出新对象的栈空间的地址,可能换成了新的地址,但是原来那个地址链接的堆空间的数据不受影响,也就是调用函数的代码中的myapple的内容完全不受影响
“在Java里面参数传递都是按值传递”这句话的意思是:按值传递是传递的值的拷贝,按引用传递其实传递的是引用的地址值,所以统称按值传递。
值传递的精髓是:传递的是存储单元中的内容,而非地址或者引用!
 
容易误解JAVA中这种传递了地址的情况是引用传递,其实不是的,不能看结果,而应该看过程的性质。JAVA中能传递地址,但是是通过值传递的方式!
而如果是引用传递,其实传递的应该是另一个地址

Java中参数传递时值传递的机制分析的更多相关文章

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

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

  2. 如何理解Java中参数传递只能传值?

    以前学习C#的时候,是完全在工作岗位上学习,一些底层较为深入的道理都不是很清楚.如今学习了Java,对于Java参数传递只能传值,不能传引用(指针)感到很困惑,在C#中不是常常说把某个引用传递到函数中 ...

  3. Java中参数传递问题

    Java中参数传递可以分为值传递和引用传递,话不多说直接撸代码 1.传原始类型(int,String等)数据是值传递 package test_1; public class Test { publi ...

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

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

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

    关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天学习 ...

  6. 关于java中是引用传递还是值传递的问题!!!经常在笔试中遇到,今天终于弄明白了!

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

  7. (转载)理解Java中的引用传递和值传递

      关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天 ...

  8. 为什么说Java中只有值传递

    本文转载自公众号 Hollis 对于初学者来说,要想把这个问题回答正确,是比较难的.在第二天整理答案的时候,我发现我竟然无法通过简单的语言把这个事情描述的很容易理解,遗憾的是,我也没有在网上找到哪篇文 ...

  9. 为什么说Java中只有值传递(转载)

    出处:https://www.hollischuang.com/archives/2275 关于这个问题,在StackOverflow上也引发过广泛的讨论,看来很多程序员对于这个问题的理解都不尽相同, ...

随机推荐

  1. php下保存远程图片到本地的函数

    <?php header("content-type:text/html;charset=utf-8"); function GrabImage($url,$filename ...

  2. PHP+tcpdf的生成

    项目中,可能用到额 查看:http://www.sucaihuo.com/php/217.html

  3. asp.net session的使用与过期实例代码

    Session的使用 <head runat="server">    <title></title>    <script src=&q ...

  4. 你与论文达人只差一个MathType的距离

    在理工类的论文文档中总是少不了数学公式的出现,各种符号夹杂在期间导致论文在编写时总是会出现各种各样的问题.但是这些问题在论文达人们手中全都不是事儿!分分钟搞定你数学公式上出现的问题!论文达人们是怎么搞 ...

  5. [大数据] zookeeper 安装和配置

    ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提供的功 ...

  6. Maven------使用maven新建web项目出现问题 项目名称出现红色交叉

    转载: http://wenda.so.com/q/1365963640069173?src=140 解决方法: problems窗口查看到下面错误java compiler level does n ...

  7. iOS-WKWebView使用

    使用代码:可直接粘贴到自己项目中使用 .h #import "BaseViewController.h" @interface LinkNewsController : BaseV ...

  8. python2.0_s12_day9_协程&Gevent协程

    Python之路,Day9 - 异步IO\数据库\队列\缓存 本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 协程 1.协程,又 ...

  9. Unity中Oculus分屏相机和普通相机一键切换

    Unity中Oculus分屏相机和普通相机一键切换 一.OCulus 分屏相机介绍 在VR开发工程中,总会觉得OC分屏的处理太慢,严重浪费时间啊! 但是不使用有不好调试,来回切换相机就成为了一个必须. ...

  10. discuz 文档说明

    Discuz  文档说明 基于7.0的标准程序,部分与插件无关的文件不作说明 文件颜色说明: 红色:程序核心文件,修改这类文件时千万要注意安全! 橙色:做插件几乎不会用到的文件,大概了解功能就可以了, ...