参数传递是什么?
     在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. ajax basic 认证

    //需要Base64见:http://www.webtoolkit.info/javascript-base64.html function make_base_auth(user, password ...

  2. Shell 启动java程序

    #!/bin/sh SHELL_PATH=$(cd ")";pwd) echo $SHELL_PATH cd "$SHELL_PATH" CLASSPATH=. ...

  3. 大型web系统数据缓存设计-l转载

    原文地址:http://www.wmyouxi.com/a/60368.html#ixzz3tGYG9JwC 1. 前言 在高访问量的web系统中,缓存几乎是离不开的:但是一个适当.高效的缓存方案设计 ...

  4. link with editor

    在左侧explore上,有个双向的箭头,点一下,就会把路径和当前文件自动对应

  5. 监听程序未启动或数据库服务未注册到该监听程序。启动该监听程序并注册数据库服务 然后重新运行 em configuration assistant。

    在WIN 7/64Bit上安装ORACLE 11gR2后,管理网页Database Control(如:https://localhost:1158/em)始终登录不进去,总是说密码错误,使用配置工具 ...

  6. fildder教程

    转载地址:写得很不错的fildder教程   http://kb.cnblogs.com/page/130367/ Fiddler的基本介绍 Fiddler的官方网站:  www.fiddler2.c ...

  7. 【SSH进阶之路】Hibernate映射——一对一双向关联映射(六)

    上篇博文[SSH进阶之路]Hibernate映射--一对一单向关联映射(五),我们介绍了一对一的单向关联映射,单向是指仅仅能从人(Person)这端载入身份证端(IdCard),可是反过来.不能从身份 ...

  8. simple fix 主从不一致滴error

    Last_SQL_Error: Error 'Unknown table 'bb'' on query. Default database: 'test'. Query: 'DROP TABLE `b ...

  9. Int 型数值存储

    1. Int 在计算机中占 4 Byte, 共 32 位, 最大正数为 2147483647, 最小负数为 -2147483648 2. 正数存储在计算机中的形式为原码,最大正数的十六进制形式为 0X ...

  10. set集合操作【python】

    set集合操作包括: >>> x=set("123defj89") >>> y=set("ab34e6jh9") >& ...