Java是值传递还是引用传递,又是怎么体现的
关于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是值传递还是引用传递,又是怎么体现的的更多相关文章
- Java是值传递还是引用传递?
Java的值传递和引用传递在面试中一般都会都被涉及到,今天我们就来聊聊这个问题.这个问题一般是相对函数而言的,也就是Java中所说的方法参数,那么我们先来回顾一下在程序设计语言中有关参数传递给方法的两 ...
- 堆栈详解 + 彻底理解Java的值传递和引用传递
本文旨在用最通俗的语言讲述最枯燥的基本知识 学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨 ...
- Java的值传递和引用传递的说法
学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨论的话题又是充满争议:有的论坛帖子说Java ...
- Java 值传递 or 引用传递?
Java 方法传参 值传递 or 引用传递? 结论:Java采用的是值传递 先建立一些基础的概念 什么是值传递和引用传递? 值传递(pass by value):是指在调用函数时将实际参数复制一份传递 ...
- Java中引用类型变量,对象,值类型,值传递,引用传递 区别与定义
一.Java中什么叫做引用类型变量?引用:就是按内存地址查询 比如:String s = new String();这个其实是在栈内存里分配一块内存空间为s,在堆内存里new了一个Stri ...
- java中值传递和引用传递
最近工作中使用到了值传递和引用传递,但是有点懵,现在看了下面的文章后清晰多了.一下是文章(网摘) 1:按值传递是什么 指的是在方法调用时,传递的参数是按值的拷贝传递.示例如下: public clas ...
- Java中的值传递和引用传递
这几天一直再纠结这个问题,今天看了这篇文章有点思路了,这跟C++里函数参数为引用.指针还是有很大区别. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里 ...
- java的值传递和引用传递
昨天博主在对于值传递和引用传递这里栽了一个大坑啊,导致一下午时间都浪费在这里,我们先说下值传递和引用传递java官方解释: 值传递:(形式参数类型是基本数据类型):方法调用时,实际参数把它的值传递给对 ...
- java中方法的参数传递机制(值传递还是引用传递)
看到一个java面试题: 问:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 答:是值传递.Java 编程语言只有值传递参 ...
- java 对象传递 是 值传递 还是 引用传递?
这个问题说实话我感觉没有太大的意义. 按第一印象和c++的一些思想去理解的话对象传递是引用传递,因为传递过去的对象的值能被改变. 但是又有很多人,不知道从哪里扣出来一句,java中只有值传递,没有引用 ...
随机推荐
- Yaml配置文件语法详解
YAML 简介 YAML,即 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写,YAML 意思其实是" Yet Ano ...
- 小程序-云数据库的add,get,remove,update
云数据库的使用就是使用简单的原生封装wx.cloud.database().collection("list"),然后就是add,get,remove,update四个方法 初始化 ...
- 一位有着近 10 年 iOS 开发经验的全职爸爸如何高效管理时间?
名字: Mindr 开发者 / 团队: Florian Vates 平台: iOS, iPadOS, Android 正在开发中 请简要介绍下这款产品 有没有发现自己总是不断推迟待办事项的通知? Mi ...
- Vscode控制台乱码的最终解决方案
Vscode控制台乱码的最终解决方案 vscode运行项目时控制台打印日志乱码.网上也有许多解决办法. 方法一[管用]推荐,避免过多设置 Java项目时,像Springboot微服务项目默认使用的是l ...
- java+mysql+tomcat环境变量配置(windows版)
jdk8(本人用的jdk8) 系统变量->新建:{JAVA_HOME=[JDK安装目录]} 系统变量->PATH:头部追加%JAVA_HOME%\bin;%JAVA_HOME%\jre\b ...
- 2023/4/21 SCRUM个人博客
1.我昨天的任务 学习信号和槽的定义并完善UI界面的基础知识 2.遇到了什么困难 难以理解design的设计理念 3.我今天的任务 学习如何使用QTdesign,并完善UI
- 18B20的CRC8校验分析
CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定. CRC校验可以简单地描述为:例如我们要 ...
- win10安装和使用wireshark
win10安装和使用wiresharkhttps://blog.csdn.net/qq_34732729/article/details/105126146https://blog.csdn.net/ ...
- 【Python】Django学习1
按黑马程序员的美多商场作方向: https://www.bilibili.com/video/BV1nf4y1k7G3 一.应用创建.注册处理.配置 Pycharm 创建Django项目: 自应用注册 ...
- 【H5】16 表单 其五 表单验证
在将数据提交到服务器之前,重要的是确保以正确的格式填写所有必需的表单控件.这称为客户端表单验证,可帮助确保所提交的数据符合各种表单控件中规定的要求.本文将引导您通过基本概念和客户端表单验证示例. 先决 ...