Java参数传递是值传递还是引用传递?
当一个对象被当作参数传递到一个方法后,在此方法内可以改变这个对象的属性,那么这里到底是值传递还是引用传递?
答:是值传递。Java 语言的参数传递只有值传递。当一个实例对象作为参数被传递到方法中时,参数的值就是该对象的引用的一个副本。指向同一个对象,对象的内容可以在被调用的方法内改变,但对象的引用(不是引用的副本) 是永远不会改变的。
Java的参数传递,不管是基本数据类型还是引用类型的参数,都是按值传递,没有按引用传递!
我们可以看一下microsoft的文档中对按引用传递参数的定义(如下截图):https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/ref#passing-an-argument-by-reference

对于参数的传递可以分为两种情况:
1.基本数据类型的参数
public class TransferTest {
public static void main(String[] args) {
int num = 1;
System.out.println("changeNum()方法调用之前:num = " + num);
changeNum(num);
System.out.println("changeNum()方法调用之后:num = " + num);
}
public static void changeNum(int x) {
x = 2;
}
}
运行结果:

传递过程的示意图如下:

分析:num作为参数传递给changeNum()方法时,是将内存空间中num所指向的那个存储单元中存放的值1复制了一份传递给了changeNum()方法中的x变量,而这个x变量也在内存空间中分配的一个存储单元。这时就把num对的值1传递给了x变量所指向的存储单元中。此后在changeNum()方法中对x变量的一切操作都是针对于x所指向的这个存储单元,与num所指向的存储单元无关。
所以,在changeNum()方法被调用后,num所指向的存储单元的值还是没有发生变化,这就是所谓的“值传递”。
值传递的精髓是:传递的是存储单元中的内容,而不是存储单元的引用。
2.引用类型的参数
示例1:
1 public class TransferTest2 {
2 public static void main(String[] args) {
3 Person person = new Person();
4 System.out.println(person);
5 change(person);
6 System.out.println(person);
7 }
8
9 public static void change(Person p) {
10 p = new Person();
11 }
12 }
13
14 /**
15 * Person类
16 */
17 class Person {
18
19 }
运行结果:

可以看出两次打印结果一致。即调用change()方法后,person变量并没发生改变。
传递过程的示意图如下:

分析:
01.当程序执行到第3行 Person person = new Person()时,程序在堆内存(heap)中开辟了一块内存空间用来存储Person类实例对象,同时在栈内存(stack)中开辟了一个存储单元来存储该实例对象的引用,即上图中person指向的存储单元。
02.当程序执行到第5行 change(person)时,person作为参数(实参)传递给饿了change()方法。这里是person将自己的存储单元的内容传递给了change()方法的p变量。此后在change()方法中对p变量的一切操作都是针对于p变量所指向的存储单元,与perosn所指向的存储单元就没有关系了。
示例2:
public class P {
String name = "P";
public P(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
public class Test {
static P p1 = new P("p1");
public static void main(String[] args) {
P p = new P("P");
System.out.println("before change p:" + p.toString);
changeObj(p);
System.out.println("after change p:" + p.toString());
}
static void changeObj(P p) {
p = new P("pp");
System.out.println("change p:" + p.toString());
//p = p1;
//System.out.println(p.toString());
}
}
运行结果:

首先要理解 “=” 赋值操作的意义:
对于基本数据类型来说 “=”赋值操作是直接改变内存地址(存储单元)上的值。
对于引用类型来说 “=” 赋值操作是改变引用变量所指向的内存地址(上文中存储单元)。
调用changeObj()方法进入第21行:

执行22行后:

所以对外部的p变量是没有影响的。
总结:
函数参数传递其实是一个赋值的过程,基本类型传递的是数值,引用类型传递的引用对象的内存地址。
另外一点要特别注意,函数的参数其实是函数内部的局部变量。不要跟外部变量混淆。
示例3:
package cn.canshu;
class Person{
private int id;
private String name;
public Person(int id,String name) {
this.id = id;
this.name = name;
}
}
public class Demo02 {
public static void main(String[] args) {
Person a = new Person(23, "a");
Person b = new Person(22,"b");
System.out.println("交换前\na:"+a+"\nb:"+b);
swap(a, b);
System.out.println("交换后\na:"+a+"\nb:"+b);
}
private static void swap(Person a, Person b) {
Person temp = a;
a = b;
b = temp;
}
}
运行结果:

同理,外部的ab引用不是内部的ad引用,故不会发生改变。
我们可以发现,Java方法的传值,实际上是把实参的值—-对象引用(对象的内存地址)传递给了形参,从而形参和实参的值(即变量里存储的内存地址,非变量本身的内存地址)是相同的,指向了同一个对象/内存地址。
Java参数传递是值传递还是引用传递?的更多相关文章
- java中方法的参数传递机制(值传递还是引用传递)
看到一个java面试题: 问:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 答:是值传递.Java 编程语言只有值传递参 ...
- java参数传递时到底是值传递还是引用传递
java参数传递时到底是值传递还是引用传递(baidu搜集) 问”,很多人的BLOG里都引用这些面试题,最近因为工作内容比较枯燥,也来看看这些试题以调节一下口味,其中有一道题让我很费解. 原题是:当一 ...
- java中参数传递--值传递,引用传递
java中的参数传递——值传递.引用传递 参数是按值而不是按引用传递的说明 Java 应用程序有且仅有的一种参数传递机制,即按值传递. 在 Java 应用程序中永远不会传递对象,而只传递对象引用. ...
- Java的参数传递是值传递还是引用传递?
一.前言 首先先说结论,Java中方法参数传递方式是按值传递.如果参数是基本类型,传递的是基本类型的字面量值的拷贝.如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝. 接下来深入了解一 ...
- java中值传递和引用传递
最近工作中使用到了值传递和引用传递,但是有点懵,现在看了下面的文章后清晰多了.一下是文章(网摘) 1:按值传递是什么 指的是在方法调用时,传递的参数是按值的拷贝传递.示例如下: public clas ...
- Java中的值传递和引用传递
这几天一直再纠结这个问题,今天看了这篇文章有点思路了,这跟C++里函数参数为引用.指针还是有很大区别. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里 ...
- JavaScript 函数参数传递到底是值传递还是引用传递
tips:这篇文章是听了四脚猫的js课程后查的,深入的理解可以参看两篇博客: JavaScript数据类型--值类型和引用类型 JavaScript数据操作--原始值和引用值的操作本质 在传统的观念里 ...
- Does Java pass by reference or pass by value?(Java是值传递还是引用传递) - 总结
这个话题一直是Java程序员的一个热议话题,争论不断,但是不论是你百度搜也好还是去看官方的文档中所标明的也好,得到的都只有一个结论:Java只有值传递. 在这里就不贴代码细致解释了,让我们来看看一些论 ...
- Java是值传递还是引用传递?
Java的值传递和引用传递在面试中一般都会都被涉及到,今天我们就来聊聊这个问题.这个问题一般是相对函数而言的,也就是Java中所说的方法参数,那么我们先来回顾一下在程序设计语言中有关参数传递给方法的两 ...
随机推荐
- Debug使用
目录 Debug使用 Debug使用
- 【转载】Linux进程间通信(六):共享内存 shmget()、shmat()、shmdt()、shmctl()
来源:https://www.cnblogs.com/52php/p/5861372.html 下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相 ...
- PAT-1005 Spell It Right 解答(C/C++/Java/python)
1.Description: Given a non-negative integer N, your task is to compute the sum of all the digits of ...
- git中常混淆的操作
1, git fetch 和 git pull 参考链接: https://stackoverflow.com/questions/292357/what-is-the-difference-betw ...
- Objective-C编程 — 并行编程
多线程 线程的基本概念 线程 (thread)是进程(process)A 内假想的持有 CPU 使用权的执行单位.一般情况下,一个进程 只有一个线程,但也可以创建多个线程并在进程中并行执行.应用在执行 ...
- vue目录结构熟悉
给项目的入口文件做点小改变: [补充:编辑器建议使用vscode,我还没装,暂时先用phpstorm] 打开 APP.vue 文件,代码如下(解释在注释中) <!-- 展示模板 --> & ...
- C#中的WinFrom技术实现串口通讯助手(附源码)
C#中的WinFrom技术实现串口通讯助手(附源码) 实现的功能: 1.实现自动加载可用串口. 2.打开串口,并且使用C#状态栏显示串口的状态. 3.实现了串口的接收数据和发送数据功能. 4.串口 ...
- vue 注意
Path Intellisense 插件 @路径提醒 配置文件中配置: "path-intellisense.mappings": { "@": "$ ...
- 【macOS使用技巧】使用空格键快速预览文件内容
Quickview 是mac系统上一个强大的预览功能, 可以预览 mp4 mov等音频文件, 当然图片.文本.也都可以进行预览. 在系统中如果你希望快速浏览一下文件而不想打开的文件的话只要选择文件然后 ...
- LCT[Link-Cut-Tree学习笔记]
部分摘抄于 FlashHu candy99 所以文章篇幅较长 请有足够的耐心(不是 其实不用学好splay再学LCT的-/kk (至少现在我平衡树靠fhq) 如果学splay的话- 也许我菜吧-LCT ...