关于Java是值传递还是引用传递,可以从代码层面来实现一下拿到结果

执行下面的代码:

    public static void main(String[] args) {
int num = 10;
String name = "Tom";
modify(num, name);
System.out.println("第3次打印int:" + num);
System.out.println("第3次打印String:" + name);
System.out.println("------------------------------------");
} public static void modify(int n, String str){
System.out.println("第1次打印int:" + n);
System.out.println("第1次打印String:" + str);
System.out.println("------------------------------------"); // 尝试在方法内部修改传进来的参数
n = 999;
str = "ABC";
System.out.println("第2次打印int:" + n);
System.out.println("第2次打印String:" + str);
System.out.println("------------------------------------");
}

打印出来的结果如下:

第1次打印int:10
第1次打印String:Tom
------------------------------------
第2次打印int:999
第2次打印String:ABC
------------------------------------
第3次打印int:10
第3次打印String:Tom
------------------------------------

可以看到无论是基本类型还是引用类型,传参数进去的时候的值和执行完modify方法后的值是一样的,也就是第1次打印和第三次打印是一样的。可是为什么明明在第2次已经修改成功了,第3次却又变回去了呢?

尝试换个方法把参数拿出来,

    public static void main(String[] args) {
int num = 10;
String name = "Tom";
int modifiedNum = modifyAndReturn(num);
String modifiedName = modifyAndReturn(name);
System.out.println("打印num:" + num);
System.out.println("打印name:" + name);
System.out.println("------------------------------------");
System.out.println("打印modifiedNum:" + modifiedNum);
System.out.println("打印modifiedName:" + modifiedName);
} public static int modifyAndReturn(int n){
System.out.println("modifyAndReturn第1次打印int:" + n); // 尝试在方法内部修改传进来的参数
n = 999;
System.out.println("modifyAndReturn第2次打印int:" + n);
System.out.println("------------------------------------");
return n;
} public static String modifyAndReturn(String str){
System.out.println("modifyAndReturn第1次打印String:" + str); // 尝试在方法内部修改传进来的参数
str = "ABC";
System.out.println("modifyAndReturn第2次打印String:" + str);
System.out.println("------------------------------------");
return str;
}

得到的结果为

modifyAndReturn第1次打印int:10
modifyAndReturn第2次打印int:999
------------------------------------
modifyAndReturn第1次打印String:Tom
modifyAndReturn第2次打印String:ABC
------------------------------------
打印num:10
打印name:Tom
------------------------------------
打印modifiedNum:999
打印modifiedName:ABC

可以看到通过return出来的值,的确是被改变了的,那又是为什么导致这个改变没有应用到参数本体呢?修改下代码再次测试

public static void main(String[] args) {
int num = 10;
String name = "Tom";
// 打印num和str的地址
System.out.println("修改前,传参前:");
System.out.println(System.identityHashCode(num));
System.out.println(System.identityHashCode(name)); System.out.println("---------------------------");
printAddr(num, name); System.out.println("---------------------------");
System.out.println("修改后,执行完方法后:");
System.out.println(System.identityHashCode(num));
System.out.println(System.identityHashCode(name));
} public static void printAddr(int n, String str){
// 打印n和str的地址
System.out.println("修改前,传参后:");
System.out.println(System.identityHashCode(n));
System.out.println(System.identityHashCode(str)); n = 999;
str = "ABC"; // 打印n和str的地址
System.out.println("---------------------------");
System.out.println("修改后,传参后:");
System.out.println(System.identityHashCode(n));
System.out.println(System.identityHashCode(str));
}

执行结果如下

修改前,传参前:
1324119927
990368553
---------------------------
修改前,传参后:
1324119927
990368553
---------------------------
修改后,传参后:
1096979270
1078694789
---------------------------
修改后,执行完方法后:
1324119927
990368553

可以看到传参进来的参数地址是和外部定义的地址是同一个,但是修改之后会指向另一个新的地址,导致原来地址上的数据不会受到影响,这其实是一个保护机制,防止参数传入方法内被篡改指向。

下面演示引用类型的另一种情况,一些老铁可能以为是对引用类型本身的修改,其实这是不对的。

先定义一个类Person

class Person{
private String name;
private int age; public Person(String name, int age) {
this.name = name;
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} @Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

执行下面的代码,可以看到传进去的参数的属性被改变


public static void main(String[] args) {
Person person = new Person("Rosy", 24);
String [] strings = {"AAA", "BBB", "CCC"};
System.out.println("第1次打印:");
System.out.println(person);
System.out.println(Arrays.toString(strings)); modifyObjAndPrintValue(person, strings); System.out.println("---------------------------");
System.out.println("第4次打印:");
System.out.println(person);
System.out.println(Arrays.toString(strings));
} public static void main5(String[] args) {
Person person = new Person("Rosy", 24);
String [] strings = {"AAA", "BBB", "CCC"};
System.out.println("第1次打印:");
System.out.println(System.identityHashCode(person));
System.out.println(System.identityHashCode(person.getAge()));
System.out.println(System.identityHashCode(person.getName()));
System.out.println(System.identityHashCode(strings)); modifyObj(person, strings); System.out.println("---------------------------");
System.out.println("第4次打印:");
System.out.println(System.identityHashCode(person));
System.out.println(System.identityHashCode(person.getAge()));
System.out.println(System.identityHashCode(person.getName()));
System.out.println(System.identityHashCode(strings));
} public static void modifyObjAndPrintValue(Person person, String [] strings){
System.out.println("---------------------------");
System.out.println("第2次打印:");
System.out.println(person);
System.out.println(Arrays.toString(strings)); person.setAge(1024);
person.setName("ABC");
strings[0] = "XXX"; System.out.println("---------------------------");
System.out.println("第3次打印:");
System.out.println(person);
System.out.println(Arrays.toString(strings));
}

执行结果为

第1次打印:
Person{name='Rosy', age=24}
[AAA, BBB, CCC]
---------------------------
第2次打印:
Person{name='Rosy', age=24}
[AAA, BBB, CCC]
---------------------------
第3次打印:
Person{name='ABC', age=1024}
[XXX, BBB, CCC]
---------------------------
第4次打印:
Person{name='ABC', age=1024}
[XXX, BBB, CCC]

从结果可以发现,Person对象的属性都被修改,String数组的元素也被修改,说明参数里对属性或数组的修改是会影响对象本身的,具体可以打印地址再查看一下:


public static void main(String[] args) {
Person person = new Person("Rosy", 24);
String [] strings = {"AAA", "BBB", "CCC"};
System.out.println("第1次打印:");
System.out.println(System.identityHashCode(person));
System.out.println(System.identityHashCode(person.getAge()));
System.out.println(System.identityHashCode(person.getName()));
System.out.println(System.identityHashCode(strings));
System.out.println(System.identityHashCode(strings[0])); modifyObjAndPrintAddr(person, strings); System.out.println("---------------------------");
System.out.println("第4次打印:");
System.out.println(System.identityHashCode(person));
System.out.println(System.identityHashCode(person.getAge()));
System.out.println(System.identityHashCode(person.getName()));
System.out.println(System.identityHashCode(strings));
System.out.println(System.identityHashCode(strings[0]));
} public static void modifyObjAndPrintAddr(Person person, String [] strings){
System.out.println("---------------------------");
System.out.println("第2次打印:");
System.out.println(System.identityHashCode(person));
System.out.println(System.identityHashCode(person.getAge()));
System.out.println(System.identityHashCode(person.getName()));
System.out.println(System.identityHashCode(strings));
System.out.println(System.identityHashCode(strings[0])); person.setAge(1024);
person.setName("ABC");
strings[0] = "XXX"; System.out.println("---------------------------");
System.out.println("第3次打印:");
System.out.println(System.identityHashCode(person));
System.out.println(System.identityHashCode(person.getAge()));
System.out.println(System.identityHashCode(person.getName()));
System.out.println(System.identityHashCode(strings));
System.out.println(System.identityHashCode(strings[0]));
}
第1次打印:
990368553
1096979270
1078694789
1831932724
1747585824
---------------------------
第2次打印:
990368553
1096979270
1078694789
1831932724
1747585824
---------------------------
第3次打印:
990368553
1023892928
558638686
1831932724
1149319664
---------------------------
第4次打印:
990368553
2093631819
558638686
1831932724
1149319664

从地址上可以看到,person和strings的地址一直没有变过。而在参数内部修改的person属性和数组元素,会对这部分成员的地址进行修改,并且会应用到对象本体上。

总结下来就是,无论传的是基本类型还是引用类型,只要在方法内部尝试改变参数地址的,都只能在方法内部使用,不会影响本体,而在方法内部改变属性的,会把对应的改变应用到本体上。所以Java是值传递的,传参的时候并不是把本身传入,而是创建一个副本,当被修改指向的时候不会影响本身,修改属性由于不会修改本身的地址,因此的时候可以应用到本体上。

Java是值传递还是引用传递,又是怎么体现的的更多相关文章

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

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

  2. 堆栈详解 + 彻底理解Java的值传递和引用传递

    本文旨在用最通俗的语言讲述最枯燥的基本知识 学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨 ...

  3. Java的值传递和引用传递的说法

    学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨论的话题又是充满争议:有的论坛帖子说Java ...

  4. Java 值传递 or 引用传递?

    Java 方法传参 值传递 or 引用传递? 结论:Java采用的是值传递 先建立一些基础的概念 什么是值传递和引用传递? 值传递(pass by value):是指在调用函数时将实际参数复制一份传递 ...

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 前端开发-- Webpack 代码分割和懒加载技术

    在现代前端开发中,优化应用性能是一个至关重要的任务.Webpack 作为一个强大的打包工具,为我们提供了代码分割和懒加载的功能,可以显著提升应用的加载速度和用户体验.本文将深入解析 Webpack 的 ...

  2. ComfyUI插件:ComfyUI Impact 节点(一)

    前言: 学习ComfyUI是一场持久战,而 ComfyUI Impact 是一个庞大的模块节点库,内置许多非常实用且强大的功能节点 ,例如检测器.细节强化器.预览桥.通配符.Hook.图片发送器.图片 ...

  3. Jmeter函数助手4-RandomDate

    RandomDate函数用于生成一段时间范围内的随机日期(年月日). Format string for DateTimeFormatter (optional) (default yyyy-MM-d ...

  4. 全网最适合入门的面向对象编程教程:29 类和对象的Python实现-断言与防御性编程和help函数的使用

    全网最适合入门的面向对象编程教程:29 类和对象的 Python 实现-断言与防御性编程和 help 函数的使用 摘要: 在 Python 中,断言是一种常用的调试工具,它允许程序员编写一条检查某个条 ...

  5. 【Half-Life】 Steam 安装半条命模组

    安装办法参考自B站UP主[百科全叔]的文章 https://www.bilibili.com/read/cv543926 半条命模组在ModDB站上下载资源 https://www.moddb.com ...

  6. python高性能计算:cython使用openmp并行 —— 报错:undefined symbol: omp_get_thread_num

    test.pyx文件: from cython.parallel cimport parallel from openmp cimport omp_get_thread_num cpdef void ...

  7. 日本联合研究团队发布 Fugaku-LLM——证明大型纯 CPU 超算也可用于大模型训练

    相关: https://mbd.baidu.com/newspage/data/landingsuper?context={"nid"%3A"news_101396655 ...

  8. 2023年人工智能发展现状报告:State of AI Report 2023

    链接: https://www.stateof.ai/ ================================ Now in its sixth year, the State of AI ...

  9. 分享某Python下的mpi教程 —— A Python Introduction to Parallel Programming with MPI 1.0.2 documentation

    如题: 无意中发现了一个Python下的mpi教程<A Python Introduction to Parallel Programming with MPI 1.0.2 documentat ...

  10. 美国空军未来利用AI控制无人僚机执行空战或对地作战任务成为可能——AI算法强化学习控制无人机执行空战或对地作战成为可能

    来源: https://export.shobserver.com/baijiahao/html/640202.html https://baijiahao.baidu.com/s?id=177346 ...