结论

为了加深印象,先把结论放在文章开头。

++Java中只有值传递++。

形参与实参

在理解Java的值传递

实参Argument

实际参数,主调用函数传递给调用函数的参数

形参Parameter

形式参数,并非实际存在的变量,只在函数定义的函数内部使用。在调用函数时,实参将会给形参赋值,从而实现主调函数向调用函数传输数据的目的。

所谓的传递,就是实参给形参赋值的过程。这是我们理解值传递和引用传递的基础。

基本类型与引用类型

基本类型的变量保存值,即值就是变量自身。

而引用类型的变量的值表示对象的引用地址,而非对象自身。

Java内存空间分为 heap 和 stack。对于基本类型的局部变量而言,空间直接在 stack 中分配(例如int a,虚拟机会为a在 stack 中分配一个四字节的内存空间,用来存放a的值),而对于引用类型的局部变量而言,虚拟机会现在 stack 中分配一个四字节的空间,用来存放指向 heap 的地址,同时在 heap中分配一块地址用来存放对象。

按值传递和引用传递

按值传递

所谓值传递,就是在实参为形参赋值的时候,将值赋给形参。

而引用传递,是是在实参为形参赋值的时候,直接将引用(即地址)赋给形参。

所谓的 Java 按值传递,就是说明实参为形参赋值时,只存在值副本的拷贝。

测试代码

一个简单的测试代码:

public class ValOrRef {

public static void main(String[] args){

System.out.println("SCENE 1:--------------------");

scene1();

System.out.println("SCENE 2:--------------------");

scene2();

System.out.println("SCENE 3:--------------------");

scene3();

}

protected static void scene1(){

int argument = 1;

incrVal(argument);

System.out.println("After method invoke, argument: " + argument);

}

protected static void scene2(){

Foo argument = new Foo("original");

changeStr(argument);

System.out.println("After method invoke, argument: " + argument);

}

protected static void scene3(){

Foo argument = new Foo("original");

createNewInstance(argument);

System.out.println("After method invoke, argument: " + argument);

}

private static void incrVal(int parameter){

parameter = parameter + 1;

System.out.println("parameter: " + parameter);

}

private static void changeStr(Foo parameter){

parameter.setStr("changed");

System.out.println("parameter: " + parameter);

}

private static void createNewInstance(Foo parameter){

parameter = new Foo("Brand New");

System.out.println("parameter: " + parameter);

}

static class Foo{

private String str;

public Foo(String str){

this.str = str;

}

public String getStr() {

return str;

}

public void setStr(String str) {

this.str = str;

}

@Override

public String toString() {

return "Foo{" +

"str='" + str + '\'' +

'}';

}

}

}

先看输出的测试结果:

SCENE 1:--------------------

parameter: 2

After method invoke, argument: 1

SCENE 2:--------------------

parameter: Foo{str='changed'}

After method invoke, argument: Foo{str='changed'}

SCENE 3:--------------------

parameter: Foo{str='Brand New'}

After method invoke, argument: Foo{str='original'}

Scene1分析

对于Scene1而言,首先主调函数scene1()方法在 自己的函数调用栈上分配了一个四字节的空间,用来存放 argument的值(值为1)。然后在调用incrVal(int val)时,会在incrVal()自己的函数调用栈上,为parameter同样分配一个四字节的空间,同时拷贝一份argument的值(值为1)赋给parameter。

此时argument和parameter除了值相等之外,没有任何联系。因此在incrVal()内部修改了parameter的值对argument没有任何影响。

Scene2分析

同样对于Scene2而言,主调函数在自己的函数调用栈上分配了一个四字节空间,用来存放argument的引用,其值是指向 heap 的一个地址,虚拟机可以通过地址值从 heap 中找到指定的对象。主调函数在调用changeStr()时,虚拟机为changeStr()同样分配了四字节空间存放paramter的值,并将argument的值(指向 heap的地址)赋值给parameter。

和Scene1相同,argument 和 parameter 除了值相等外,没有其他关联。

当changeStr()内部调用paramter.setStr()时,虚拟机会根据paramter的值找到 heap 上对应的Foo对象,然后修改了Foo对象上str所指的值。

由于paramter和argument的值指向了相同的对象,因此argument的对象也发生了改变。

但赋值的过程依旧是按值传递。

Scene3分析

对于Scene3,argument保存在主调函数的函数调用栈上,然后在调用createNewInstance时,把值(表示 heap 上的某个空间地址)赋值给了parameter。而在函数内部,parameter的值又被修改成了新创建对象的地址。但是外部argument的值仍然是指向之前的对象。因此argument并未发生改变。

总结

最后在总结一次,Java 只存在按值传递。

java传参怎么理解_如何理解Java的值传递相关推荐

  1. Java传参是字节还是字符串好_深入分析java传参

    概述 java中的参数传递问题可以根据参数的类型大致可以分为三类:传递基本类型,传递String类型,传递引用类型,至于最终是否可以归纳为值传递和引用传递,根据每个人的理解不同,答案不同,此处不做强调 ...

  2. java如果不使用多态_深入理解java多态没有烤山药的存在,java就不香了吗?

    @ 我不想知道各位理解java多态没有烤山药的存在,java香不香的问题了,我不要你们认为,我只要我觉得 (感觉要被打....) 在博主认为多态绝对是面向对象的第三大特性中让很多小白同学以及初学者难以 ...

  3. 深入java虚拟机 第四版_深入理解Java虚拟机-常用vm参数分析

    Java虚拟机深入理解系列全部文章更新中... https://blog.ouyangsihai.cn/shen-ru-li-jie-java-xu-ni-ji-java-nei-cun-qu-yu- ...

  4. mybatis java传参_[Java教程]Mybatis批量和传参

    [Java教程]Mybatis批量和传参 0 2014-07-31 04:00:12 MyBatis中批量插入 方法一: resultType="java.lang.String" ...

  5. java的接口怎么理解_如何理解Java 中的接口

    一.接口(Interface) 在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明.一个类通过继承接口的方式,从而来继承接口的抽象方法.接口并不是类,编写接口的方 ...

  6. java jvm垃圾回收算法_深入理解JVM虚拟机2:JVM垃圾回收基本原理和算法

    本文转自互联网,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 喜欢的话麻烦点下Star哈 文章将同步到我的个人博客: www.how ...

  7. java中io是什么_深入理解Java中的IO

    深入理解Java中的IO 转载自:http://blog.csdn.net/qq_25184739/article/details/51205186 本文的目录视图如下: Java IO概要 a.Ja ...

  8. java虚拟机的生命周期_深入理解Java虚拟机——JVM的生命周期

    package test; public class JVMTestLife { public static void main(String[] args) { new Thread(new Run ...

  9. Java - 传参到底是哪种? pass by value or pass by reference

    在了解Java传参数是pass by value或是pass by reference之前,先了解=赋值的用法会对理解传参很有帮助 赋值(=)的用法 =的意义是赋值,但是这个赋值用在 基本类型 和 对 ...

最新文章

  1. php python-浅谈php调用python文件
  2. ps怎么对比原图快捷键_用PS快速将一张模糊不清晰的照片变清晰,简单5步就好...
  3. Win:Win系统下安装Linux的Ubuntu系统的简介、安装之详细攻略
  4. Socket的select制作多客户端传输(Qt)
  5. 认识JavaWeb,servlet, JSP, Tomcat, http协议,Web服务器
  6. linux系统in命令,Linux中的In命令
  7. 数组占位符_Java基础 方法和数组
  8. Vmarker图片标注工具使用文档
  9. vba set语句_零基础学VBA编程06:什么是变量?
  10. 树莓派引脚介绍与GPIO的初步认识与应用
  11. xyz坐标转换ybc_GNSS仰角和方位角的计算及代码,XYZ转BLH坐标的代码及原理
  12. 全球每日被黑站点一览表!
  13. python游戏开发(贪吃蛇游戏、五子棋游戏、大球吃小球游戏)
  14. android摄影程序,手机影像魅力:10款最佳Android摄影程序
  15. ChatGPT近视眼镜购买指南:防雾防尘、舒适度与价格平衡的完美选择
  16. SQL全称量词使用存在量词替代
  17. Amazon DynamoDB详解
  18. 基于MATLAB的数字信号处理(4) IIR数字滤波器设计及软件实现
  19. 【数据结构】插入排序(直接插入排序 希尔排序)
  20. Android Studio报错:Incompatible types. Required:android.app.ActionBar及Android如何隐藏系统默认标题栏

热门文章

  1. VS2010生成静态库(.lib)
  2. Node.js在不同平台的安装方法步骤详解
  3. Facebook's New Real-time Messaging System: HBase to Store 135+ Billion Messages a Month
  4. SQL Server Profiler的一个小问题
  5. Apriori算法进行关联分析(1)
  6. 一、 Log4E插件下载
  7. ref out param 区别
  8. python3+requests:get/post请求
  9. 程序员面试时这样介绍自己的项目经验,成功率能达到98.99%
  10. thinkphp5.0 使用paginate 分页后 foreach 循环体内不能处理数据的解决办法