当一个对象被当作参数传递到一个方法后,在此方法内可以改变这个对象的属性,那么这里到底是值传递还是引用传递?

答:是值传递。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参数传递是值传递还是引用传递?的更多相关文章

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

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

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

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

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

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

  4. Java的参数传递是值传递还是引用传递?

    一.前言 首先先说结论,Java中方法参数传递方式是按值传递.如果参数是基本类型,传递的是基本类型的字面量值的拷贝.如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝. 接下来深入了解一 ...

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

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

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

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

  7. JavaScript 函数参数传递到底是值传递还是引用传递

    tips:这篇文章是听了四脚猫的js课程后查的,深入的理解可以参看两篇博客: JavaScript数据类型--值类型和引用类型 JavaScript数据操作--原始值和引用值的操作本质 在传统的观念里 ...

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

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

  9. Java是值传递还是引用传递?

    Java的值传递和引用传递在面试中一般都会都被涉及到,今天我们就来聊聊这个问题.这个问题一般是相对函数而言的,也就是Java中所说的方法参数,那么我们先来回顾一下在程序设计语言中有关参数传递给方法的两 ...

随机推荐

  1. 【Java编程思想读书笔记】继承中父类的初始化方式

    继承中父类的初始化方式 p144页有感 一.提出问题 假设有一些类,这些类有继承关系的时候,当初始化一个子类对象,对于该类的父类而言,发生了什么呢?是仅仅只是复制了一个引用还是也会同时new一个父类对 ...

  2. css实现文字过长显示省略号的方法

    <div class="title">当对象内文本溢出时显示省略标记</div> 这是一个例子,其实我们只需要显示如下长度: css实现网页中文字过长截取. ...

  3. IT运维大会精华回顾 等保2.0时代掌控万物互联

    10月24日,由<网络安全和信息化>杂志社.IT运维网联合主办的“2019(第十届)IT运维大会”在北京新世纪日航酒店成功举行. 随着大数据.云计算.物联网.互联网+等快速发展,IT系统架 ...

  4. Python字符串字母大小写变换

    说明: 字符串就是一系列字符,在Python中用引号括起来的都是字符串,引号可以是单引号,也可以是双引号,比如:“This is a book.”  ‘This is an apple.’ 接下来简单 ...

  5. 移动端 location.href 无法成功跳转页面

    最近做的移动端页面在请求成功后要跳转页面,通过location.href实现的跳转.但同事在测试时,安卓机可以成功跳转,苹果IOS确无法成功跳转.   解决办法:在链接后面加一个随机参数,这样就可以跳 ...

  6. 显示层封装及实现与优化(无动画+css3动画+js动画)

    showhide.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...

  7. k8s CNI插件简单了解

    Kubernetes网络模型本身对某些特定的网络功能有一定要求,但在实现方面也具有一定的灵活性.业界已经有不少不同的网络方案,来满足特定的环境和要求. CNI(container network in ...

  8. opencv —— contourArea、arcLength 计算轮廓面积与长度

    计算轮廓面积:contourArea 函数 double contourArea(InputArray contour, bool oriented = false); contour,输入的二维点集 ...

  9. python基础入门之三 —— 字符串

    1.格式 一对引号和三对引号可以表示字符串 (三引号保留换行) 2.下标 从0开始循序向下分配 str1='abcdefg' print(str1) print(str1[0]) print(str1 ...

  10. 小白的linux笔记6:关于挂载硬盘

    每个硬盘,包括移动硬盘,插上之后都会有个名字,如sda,sdb,sdc.... sda,sdb等名字只与插上的顺序有关.而且重启后有可能会发生变化. 查看全部硬盘可以用fdisk -l. df -h  ...