基本类型的不用讨论了,就是按值传递,传递了值的一个副本,这个结论应该是没有争议了的。主要矛盾点是在引用类型数据的传递。直接亮代码,请大牛们指点一二:
package com.luke;
public class Test {
public static void main(String[] args) {
User mainUser = new User();
mainUser.age = 10;
mainUser.name = "李四";
System.out.println("主函数调用方法前的哈希码:" + mainUser.hashCode());
System.out.println("主函数调用方法前的对象参数:" + mainUser.age + "\t" + mainUser.name);
pass(mainUser);
System.out.println("主函数方法调用后的哈希码" + mainUser.hashCode());
System.out.println("主函数方法调用后的对象属性::" + mainUser.age + "\t" + mainUser.name);
}
public static void pass(User user) {
user.age = 20;
user.name = "张三";
System.out.println("方法中对象修改前的对象哈希码:" + user.hashCode());
System.out.println("方法中引用未修改但属性修改的属性:" + user.age + "\t" + user.name);
user = new User();
user.age = 30;
user.name = "王五";
System.out.println("方法中对象修改后的对象哈希码:" + user.hashCode());
System.out.println("方法中引用修改同时属性修改的属性:" + user.age + "\t" + user.name);
}
}
class User {
int age;
String name;
}
输出是:
主函数调用方法前的哈希码:366712642
主函数调用方法前的对象参数:10 李四
方法中对象修改前的对象哈希码:366712642
方法中引用未修改但属性修改的属性:20 张三
方法中对象修改后的对象哈希码:1829164700
方法中引用修改同时属性修改的属性:30 王五
主函数方法调用后的哈希码366712642
主函数方法调用后的对象属性::20 张三
大家对这个现象有什么看法?我觉得,传递对象的时候,主要看对象的哈希码就好了,跟对象的属性没太大关系,所以那些用对象的属性去证明的,不管结论是按值传递还是按引用传递,都是错误的证明方式。
你可以打印字节码,结合JVM和栈帧的知识看一下
传给pass的user肯定是引用,这个user只是一个symbol,初始时指向传入的user对象引用,后面修改指向的对象引用后,其实并不影响传入的对象引用;
可以这样理解:方法的形参,指向的是传入的引用,通过改形参可以直接修改传入的引用所引用的对象数据,这个时候是直接体现在实参上的;但是你重新new了一个对象,返回一个新的对象引用,让形参指向这个新的引用,对这个新的对象进行修改,不会影响实参。
不一定准确哈
@寻觅beyond: 大佬不要谦虚。
传入方法pass的user 是一个引用无疑了,如果后面不 执行user = new User();,传过来参数之前和之后,指向的都是原来的对象地址。这时候,修改对象的属性,属性变化了,到底算是值传递,还是引用传递?我看了很多的文章都强行认为是值传递,理由是,引用就是值。很绕很晕。水平有限,字节码栈帧的 相关知识比较缺乏。
java中八大基本类型传递的时候是值传递,相当于拷贝整个栈帧,也就是相当于复制一份值,而其他类型为引用类型,相当于拷贝了一块新的指向同一块堆内存,在user = new user();会在堆中重新开辟一块内存,传入的user对象引用指向新的内存,而在退出pass()方法后,原引用还是指向原来的内存地址
– 周光宇 3年前@周光宇: 我终于理解你说的了。引用存在栈中,调用方法传参的时候,复制这个栈中的引用,这两个引用都指向了同一个对象。所以对按值传递还是按引用传递的关注点实际上应该是关注栈上的东西,而不是堆中的东西。这就是为什么说,引用其实本事就是一个值的原因。我之前一直不理解一点。这么说来,那些通过修改引用指向的对象的属性的方式,来证明是按引用传递,其实是用错误的方式关注了错误的方向。不知道这样理解,对不对 。
– lukely 3年前