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

答:是值传递。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. 杭电-------2047阿牛的eof牛肉串(C语言写)

    /* 主要看最后一个是否为O,若为O,则倒数第二个不能为O,则为a[n-2]*1*2; 若不为O,则最后一个有两个选择则为a[n-1]*2 */ #include<stdio.h> ] = ...

  2. C语言快速排序函数------qsort();

    #include<stdio.h> #include<stdlib.h> #include<string.h> #include<conio.h> ty ...

  3. 领域驱动设计(DDD)实践之路(一)

    本文首发于 vivo互联网技术 微信公众号 链接: https://mp.weixin.qq.com/s/gk-Hb84Dt7JqBRVkMqM7Eg  作者:张文博 领域驱动设计(Domain Dr ...

  4. 使用Python爬虫库BeautifulSoup遍历文档树并对标签进行操作详解(新手必学)

    为大家介绍下Python爬虫库BeautifulSoup遍历文档树并对标签进行操作的详细方法与函数下面就是使用Python爬虫库BeautifulSoup对文档树进行遍历并对标签进行操作的实例,都是最 ...

  5. JavaScript-迭代器模式

    迭代器模式 顺序访问一个集合 使用者无需知道集合内部结构(封装) jQuery 示例 <!DOCTYPE html> <html> <head> <meta ...

  6. css常用样式font控制字体的多种变换

    CSS 字体属性定义文本的字体系列.大小.加粗.风格(如斜体)和变形(如小型大写字母)font-family控制字体,由于各个电脑系统安装的字体不尽相同,但是基本装有黑体.宋体与微软雅黑这三款字体,通 ...

  7. 配置 Apache James 邮件服务器以使用加密邮件通讯协议

    可先参照: 使用 Apache James 3.3.0(开源免费) 搭建内网电子邮件服务器(基于 Windows + Amazon Corretto 8)https://www.cnblogs.com ...

  8. openlayers6结合geoserver实现地图矢量瓦片(附源码下载)

    内容概览 1.基于openlayers6结合geoserver实现地图矢量瓦片2.源代码demo下载 效果图如下: 实现思路:利用Geoserver发布矢量切片服务,然后openlayers调用矢量瓦 ...

  9. 【idea激活码】,【WebStorm激活码】,【DataGrip激活码】,【IntelliJ 全家桶系列】,【定期更新】,【第一期】

    IntelliJ IDEA.PyCharm.PhpStorm.WebStorm.RubyMide.AppCode.CLion.GoLand.DataGrip.Rider.Android Studio可 ...

  10. #《Essential C++》读书笔记# 第四章 基于对象的编程风格

    基础知识 Class的定义由两部分组成:class的声明,以及紧接在声明之后的主体.主体部分由一对大括号括住,并以分号结尾.主体内的两个关键字public和private,用来标示每个块的" ...