Java 方法传参 值传递 or 引用传递?

结论:Java采用的是值传递

先建立一些基础的概念

什么是值传递和引用传递?

  • 值传递(pass by value):是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数
  • 引用传递(pass by reference):是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数

Java的数据类型分为两类

  • 基本类型(int float等)
  • 引用类型(string, 数组等, 以及一切类对象)

如下图,展示了两者在内存中存储形式,基本类型存储的是值,而引用类型存储的是地址,该地址指向值所在的内存空间。引用类型有点类似于C语言中的指针。

实践出真知,本文做了三个实验来论证为什么Java是值传递。

实验一:证明基本类型是值传递

先上代码

public class test {

    public static void main(String[] args) {
int a = 1000;
changeInt(a);
System.out.println("(main)a = " + a);
} private static void changeInt(int a) {
a = 3;
System.out.println("(changeInt)a = " + a);
}
} // 运行代码会得到如下结果
// (changeInt)a = 3
// (main)a = 1000

在代码中,我们向changInt方法传入了变量a,并在方法内部中改变了a的值,但主程序中a的值并没有改变。因此基本类型是值传递。

实验二:引用类型是引用传递?

先上代码

public class test {
public static void main(String[] args) {
Student std = new Student();
std.name = "Nick";
changeStd(std);
System.out.println("(main)name = " + std.name);
} private static void changeStd(Student std) {
std.name = "Paul";
System.out.println("(change)name = " + std.name);
}
} class Student {
String name;
} // 运行结果
// (change)name = Paul
// (main)name = Paul

在上段代码中,我们向changeStd方法传入了一个student类实例,并在方法内部中改变了学生类实例中的name字段。从运行的结果我们可以看出主程序中的学生实例的姓名也被改变。难道引用类型采用的是引用传递?当然不是,接下来继续看第三个实验。

实验三:引用类型是值传递?

public class test {
public static void main(String[] args) {
Student std = new Student();
std.name = "Nick";
changeStd(std);
System.out.println("(main)name = " + std.name);
} private static void changeStd(Student std) {
std = new Student();
std.name = "Paul";
System.out.println("(change)name = " + std.name);
}
} class Student {
String name;
} // 运行结果
// (change)name = Paul
// (main)name = Nick

我们改变了方法内部的赋值,我们先重新给std创建了一个新的学生实例,并将名字修改。其结果与实验二相反,方法内部的赋值操作并未改变。难道引用类型又是值传递?

总结

要想理解三个实验的运行结果,其实原理并不复杂。

实验一:下图表示的是,两个变量的内存情况。只有可能是两个a有着不同的地址,方法内部的赋值才不会改变主程序的a值。如果两者是同一内存空间,那么方法内部的修改,必定会影响主程序的a值。

实验二:下图表示的是方法内部还未赋值的时候,两个变量的内存情况。两个变量虽然有着不同的内存空间,但是存储都是Nick的地址,实际指向的是同一个地址空间。有了Nick的存储地址,当然可以方法内部去改变Nick的值。

赋值后

实验三:与实验二相同,在还未创建新的实例时,两者指向的都是Nick。但是在给方法内部的std赋值之后,实际上改变了其存放的地址,将其指向了一个新的对象Paul。

根据三个实验的结果,我们可以论证出Java采用的是值传递,只不过对于基本类型而言,传递的是一个具体的值,而对于引用类型而言传递的也是一个具体的值,只不过这个值是一个地址。而有这个地址,我们可以对地址指向的地址空间进行操作,所以会出现实验二的情况,但是如果我们对值本身进行改变赋值,两者是互不影响的。

看到一个例子说的很形象:

Java 值传递 or 引用传递?的更多相关文章

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

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

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

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

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

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

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

    昨天博主在对于值传递和引用传递这里栽了一个大坑啊,导致一下午时间都浪费在这里,我们先说下值传递和引用传递java官方解释: 值传递:(形式参数类型是基本数据类型):方法调用时,实际参数把它的值传递给对 ...

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

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

  6. java 对象传递 是 值传递 还是 引用传递?

    这个问题说实话我感觉没有太大的意义. 按第一印象和c++的一些思想去理解的话对象传递是引用传递,因为传递过去的对象的值能被改变. 但是又有很多人,不知道从哪里扣出来一句,java中只有值传递,没有引用 ...

  7. java参数传递时到底是值传递还是引用传递

    java参数传递时到底是值传递还是引用传递(baidu搜集) 问”,很多人的BLOG里都引用这些面试题,最近因为工作内容比较枯燥,也来看看这些试题以调节一下口味,其中有一道题让我很费解. 原题是:当一 ...

  8. Java面向对象-方法的值传递和引用传递

    Java面向对象-方法的值传递和引用传递 0 发布时间:『 2016-08-21 14:21』  博客类别:Java核心基础  阅读(197) 评论(0) Java面向对象-方法的值传递和引用传递 方 ...

  9. Does Java pass by reference or pass by value?(Java是值传递还是引用传递) - 总结

    这个话题一直是Java程序员的一个热议话题,争论不断,但是不论是你百度搜也好还是去看官方的文档中所标明的也好,得到的都只有一个结论:Java只有值传递. 在这里就不贴代码细致解释了,让我们来看看一些论 ...

  10. Java值传递和引用传递

    Java总是在讨论是传递还是引用传递,Java没有像C语言那样拥有指针,在看到引用传递和值传递很多的解释之后,更相信引用传递和值传递归根到底都是值传递,只不过引用传递的时候看上去很高大上,其实是把变量 ...

随机推荐

  1. petite-vue源码剖析-优化手段template详解

    什么是<template>元素? <template>是2013年定稿用于提供一种更统一.功能更强大的模板本存放方式.具体表现为 通过<template>元素属性c ...

  2. LGP2490题解

    有点儿神秘? 根据他这个题意说的,白子向右的第一个一定是对应的黑子啊. 所以棋子的绝对位置是不重要的,我们只需要考虑白子和黑子的相对位置,然后考虑用 GF 来拼凑状态就好了. 下面的 \(k\) 是题 ...

  3. RESTful API设计规范总结

    RESTful 是目前最流行的 API 设计规范,用于 Web 数据接口的设计. 它的大原则容易把握,但是细节不容易做对.本文总结 RESTful 的设计细节,介绍如何设计出易于理解和使用的 API. ...

  4. 算法 | Java 常见排序算法(纯代码)

    目录 汇总 1. 冒泡排序 2. 选择排序 3. 插入排序 4. 快速排序 5. 归并排序 6. 希尔排序 6.1 希尔-冒泡排序(慢) 6.2 希尔-插入排序(快) 7. 堆排序 8. 计数排序 9 ...

  5. [SPDK/NVMe存储技术分析]014 - (NVMe over PCIe)Host端的命令处理流程

    NVMe over PCIe最新的NVMe协议是1.3. 在7.2.1讲了Command Processing流程.有图有真相. This section describes command subm ...

  6. bzoj3144 [HNOI2013]切糕(最小割)

    bzoj3144 [HNOI2013]切糕(最小割) bzoj Luogu 题面描述见上 题解时间 一开始我真就把这玩意所说的切面当成了平面来做的 事实上只是说相邻的切点高度差都不超过 $ d $ 对 ...

  7. Spring Boot 2.X 有什么新特性?与 1.X 有什么区别?

    配置变更JDK 版本升级第三方类库升级响应式 Spring 编程支持HTTP/2 支持配置属性绑定更多改进与加强-

  8. List、Map、Set 三个接口存取元素时,各有什么特点?

    List 以特定索引来存取元素,可以有重复元素.Set 不能存放重复元素(用对象的 equals()方法来区分元素是否重复).Map 保存键值对(key-value pair)映射, 映射关系可以是一 ...

  9. 什么是 bean 的自动装配?

    Spring 容器能够自动装配相互合作的 bean,这意味着容器不需要和配置,能通 过 Bean 工厂自动处理 bean 之间的协作.

  10. Linux 中进程有哪几种状态?在 ps 显示出来的信息中, 分别用什么符号表示的?

    1.不可中断状态:进程处于睡眠状态,但是此刻进程是不可中断的.不可中断, 指进程不响应异步信号. 第 441 页 共 485 页2.暂停状态/跟踪状态:向进程发送一个 SIGSTOP 信号,它就会因响 ...