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

答:是值传递。Java 语言的参数传递只有值传递。当一个实例对象作为参数被传递到方法中时,参数的值就是该对象的引用的一个副本。指向同一个对象,对象的内容可以在被调用的方法内改变,但对象的引用(不是引用的副本) 是永远不会改变的。

Java的参数传递,不管是基本数据类型还是引用类型的参数,都是按值传递,没有按引用传递!

我们可以看一下microsoft的文档中对按引用传递参数的定义(如下截图):https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/ref#passing-an-argument-by-reference

对于参数的传递可以分为两种情况:

1.基本数据类型的参数

 1 public class TransferTest {
2 public static void main(String[] args) {
3 int num = 1;
4 System.out.println("changeNum()方法调用之前:num = " + num);
5 changeNum(num);
6 System.out.println("changeNum()方法调用之后:num = " + num);
7 }
8
9 public static void changeNum(int x) {
10 x = 2;
11 }
12 }

运行结果:

传递过程的示意图如下:

分析: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:

 1 public class P {
2 String name = "P";
3 public P(String name) {
4 this.name = name;
5 }
6 @Override
7 public String toString() {
8 return name;
9 }
10 }
11
12 public class Test {
13 static P p1 = new P("p1");
14 public static void main(String[] args) {
15 P p = new P("P");
16      System.out.println("before change p:" + p.toString);
17 changeObj(p);
18 System.out.println("after change p:" + p.toString());
19 }
20
21 static void changeObj(P p) {
22 p = new P("pp");
23 System.out.println("change p:" + p.toString());
24 //p = p1;
25 //System.out.println(p.toString());
26 }
27 }

运行结果:

首先要理解 “=” 赋值操作的意义:

对于基本数据类型来说 “=”赋值操作是直接改变内存地址(存储单元)上的值。

对于引用类型来说 “=” 赋值操作是改变引用变量所指向的内存地址(上文中存储单元)。

调用changeObj()方法进入第21行:

执行22行后:

所以对外部的p变量是没有影响的。

总结:

函数参数传递其实是一个赋值的过程,基本类型传递的是数值,引用类型传递的引用对象的内存地址。

另外一点要特别注意,函数的参数其实是函数内部的局部变量。不要跟外部变量混淆。

示例3:

 1 package cn.canshu;
2 class Person{
3 private int id;
4 private String name;
5 public Person(int id,String name) {
6 this.id = id;
7 this.name = name;
8 }
9 }
10 public class Demo02 {
11 public static void main(String[] args) {
12 Person a = new Person(23, "a");
13 Person b = new Person(22,"b");
14 System.out.println("交换前\na:"+a+"\nb:"+b);
15 swap(a, b);
16 System.out.println("交换后\na:"+a+"\nb:"+b);
17 }
18 private static void swap(Person a, Person b) {
19 Person temp = a;
20 a = b;
21 b = temp;
22 }
23 }

运行结果:

同理,外部的ab引用不是内部的ad引用,故不会发生改变。

我们可以发现,Java方法的传值,实际上是把实参的值—-对象引用(对象的内存地址)传递给了形参,从而形参和实参的值(即变量里存储的内存地址,非变量本身的内存地址)是相同的,指向了同一个对象/内存地址。

在此之前是转的其他博主:https://www.cnblogs.com/9513-/p/8484071.html

===================================我是分割线==========================================================================================

示例4

class Person{
private int id;
private String name;
public Person(int id,String name) {
this.id = id;
this.name = name;
}
//省略get,set方法
  //省略toString方法
} public void demo(){
Person person = new Person("张三",1);
 sout(person);
 demo2(person);
 sout(person);
} public void demo2(Person person1){
person.setName ="李四"
person.setId=2
  sout(person1)
}

运行结果:

改变前:person{name=‘张三’,age=1}

    person{name=‘李四’,age=2}

改变后:person{name='李四',age=2}

把person对象的地址的引用传给了person1 ,所以person和person1指向的是同一个内存地址。

总结一下:JAVA方法的传值,基本数据类型是值传递,引用数据类型(不包含String类型)是值传递【地址值的传递】,如果方法里有person1=new Person【new对象】,或者是给对象person1赋值了一个地址值。原来的(person)对象不改变,如果只是改变person1的属性,person的属性值也会跟着改变。

如果有疏漏,请指正(* ̄︶ ̄)!!!

JAVA方法中参数到底是值传递还是引用传递的更多相关文章

  1. Java方法的参数传递方式为: 值传递

    Java方法的参数传递方式为: 值传递 对于基本数据类型作为参数传递时, 是"按值传递", 这点都认识很清楚. 但是, 当对象或者说引用作为参数传递, Java 的参数传递方式是& ...

  2. 辨析Java方法参数中的值传递和引用传递

    小方法大门道 小瓜瓜作为一个Java初学者,今天跟我说她想通过一个Java方法,将外部变量通过参数传递到方法中去,进行逻辑处理,方法执行完毕之后,再对修改过的变量进行判断处理,代码如下所示. publ ...

  3. java中方法传入参数时:值传递还是址传递?

    JAVA中的数据类型有两大类型: ① 基本数据类型:逻辑型(boolean).文本型(char).整数型(byte.short.int.long).浮点型(float.double) ② 引用数据类型 ...

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

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

  5. Java中到底是值传递还是引用传递?

    Java中到底是值传递还是引用传递? 我们先回顾一下基本概念 实参和形参 参数在编程语言中是执行程序需要的数据,这个数据一般保存在变量中.在Java中定义一个方法时,可以定义一些参数, 举个例子: p ...

  6. 【Java思考】Java 中的实参与形参之间的传递到底是值传递还是引用传递呢?

    科普: 值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数. 引用传递(pass by reference)是指在 ...

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

    答:是值传递.Java编程语言只有值传递参数. 当一个对象实例作为一个参数被传递到方法中时,参数的值就是该对象的引用一个副本.指向同一个对象,对象的内容可以在被调用的方法中改变,但对象的引用(不是引用 ...

  8. Java调用函数传递参数到底是值传递还是引用传递

    今天翻看微信上有关Java技术的公众号时,看到了一篇关于Java中值传递的问题,文章讨论了在Java中调用函数进行传参的时候到底是值传递还是引用传递这个面试时会问到的问题.之前也接触过类似的问题,但只 ...

  9. 【java】值传递和引用传递---对象作为方法的参数传入属于哪种传递

    首先 这篇作为一个永久性的问题,欢迎大家讨论 其次,个人结论如下几条: ①Java有且只有一种传递,即 值传递 ②作为方法的参数传入,都是对原本的实参进行了copy ③只不过[实参]若是[基本数据类型 ...

随机推荐

  1. 机器学习(ML)十二之编码解码器、束搜索与注意力机制

    编码器—解码器(seq2seq) 在自然语言处理的很多应用中,输入和输出都可以是不定长序列.以机器翻译为例,输入可以是一段不定长的英语文本序列,输出可以是一段不定长的法语文本序列,例如 英语输入:“T ...

  2. GitHub新手教学(从新手安装到初步使用)

    版权声明:本文为博主原创文章,转载请标明出处! 博客地址:http://blog.csdn.net/qazwsxpcm https://blog.csdn.net/qazwsxpcm/article/ ...

  3. Python原来这么好学-2.1节: 选择PyCharm作为开发工具

    这是一本教同学们彻底学通Python的高质量学习教程,认真地学习每一章节的内容,每天只需学好一节,帮助你成为一名卓越的Python程序员: 本教程面向的是零编程基础的同学,非科班人士,以及有一定编程水 ...

  4. [redis读书笔记] 第二部分 单机数据库 数据库实现

    一 数据库基本实现/命令下发的实现 redis.c里,大家能看到redisCommandTable[] 的实现,列出了支持的所有命令.大部分的入参为redisClient *c,当一条REDIS命令下 ...

  5. [redis读书笔记] 第一部分 数据结构与对象 对象类型

    - 从前面redis的基本数据结构来看,可以看出,redis都是在基本结构(string)的基础上,封装了一层统计的结构(SDS),这样让对基本结构的访问能够更快更准确,提高可控制度. - redis ...

  6. win10配置CUDA+Tensorflow2.0的一些经验

    目录 问题描述 安装 tensorflow-cpu-2.0 编译 Nvidia Samples 问题描述 网上已经很多关于配置CUDA的文章,自己这篇文章只是个大致的安装步骤,文章重点是安装和配置的一 ...

  7. 智和网管平台SugarNMS网络综合监控等级保护安全解决方案

    IT运维是一个很大的范畴,涉及到的部门.架构.技术.产品十分广泛.北京智和信通以等保标准为依据,依托丰富的网络安全行业经验,配套自主研发的智和网管平台SugarNMS,提升用户网络关键基础设施综合管理 ...

  8. 01、Git安装教程(windows)

    首先如下图:(点击next) 第二步:文件位置存储,可根据自己盘的情况安装 第三步:安装配置文件,自己需要的都选上,下一步 第四步:不创建启动文件夹,下一步: 第五步:选择默认的编辑器,我们直接用推荐 ...

  9. 在虚拟机中使用NetToPLCSim和PLC相连.

    1,虚拟机...系统Win10...里面安装了VS. 2,本机...系统Win10...里面安装了博图15. 3,转换软件:NetToPLCSIM. 4,本机和虚拟机连接同一个路由器.注意: 5,设置 ...

  10. java设计模式--迪米特法则

    基本介绍 1.一个对象应该对其他对象保持最少的了解 2.类与类关系越密切,耦合度越大 3.迪米特法则又叫最少知道原则,即一个类对自己依赖的类知道的越少越好.也就是说,对于被依赖的类不管多么复杂,都尽量 ...