java基本数据类型传递与引用传递区别详解
程序设计语言中有关参数传递给方法(或函数)的两个专业术语:
按值调用(call by value) 按引用调用(call by reference)
所谓的按值调用表示方法接收的是调用着提供的值
按引用调用则表示方法接收的是调用者提供的变量地址
这里我们需要注意的是一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值,这句话相当重要
1.基本数据类型的传递和修改
public static void main(String[] args) { int x = 10; System.out.println(x); setInt(x); System.out.println(x); } /* * 基本数据类型的传递和修改 */ public static void setInt(int x) { x = x * 3; }
结果
10 10
说明x并没有被修改
参照下图
分析:
1)value被初始化为x值的一个拷贝(也就是10)
2)value被乘以3后等于30,但注意此时x的值仍为10!
3)这个方法结束后,参数变量value不再使用,被回收。
结论:当传递方法参数类型为基本数据类型(数字以及布尔值)时,一个方法是不可能修改一个基本数据类型的参数。
2.引用数据类型的传递和修改
用户对象
public class UserInfo { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
2.1内部方法修改对象值后,外部对象值也被更新了
public static void main(String[] args) { UserInfo user1 = new UserInfo(); user1.setId(1); user1.setName("张三"); System.out.println(user1.getId()+" - "+user1.getName()); System.out.println("=====setUser1====="); setUser1(user1); System.out.println(user1.getId()+" - "+user1.getName()); } public static void setUser1(UserInfo ui) { ui.setId(10); ui.setName("修改后的名字"); }
结果
1 - 张三 =====setUser1===== 10 - 修改后的名字
分析:
1)ui变量被初始化为user1值的拷贝,这里是一个对象的引用。
2)调用ui变量的set方法作用在这个引用对象上,user1和ui同时引用的User对象内部值被修改。
3)方法结束后,ui变量不再使用,被释放,而user还是没有变,依然指向User对象。
结论:当传递方法参数类型为引用数据类型时,一个方法将修改一个引用数据类型的参数所指向对象的值。
参照下图
2.2内部方法重新指向新的对象,修改值后,外部对象值未被更新
public static void main(String[] args) { UserInfo user1 = new UserInfo(); user1.setId(1); user1.setName("张三"); System.out.println(user1.getId()+" - "+user1.getName()); System.out.println("=====setUser2====="); setUser2(user1); System.out.println(user1.getId()+" - "+user1.getName()); } public static void setUser2(UserInfo ui) { ui = new UserInfo(); ui.setId(10); ui.setName("修改后的名字"); }
结果
1 - 张三 =====setUser2===== 1 - 张三
分析:
1)ui变量被初始化为user1值的拷贝,这里是一个对象的引用。
2)ui重新实例化,此时ui与user1已经不是同时引用的User对象。
3)ui调用set赋值后,修改的是新的对象,此时User并没有被修改。
4)方法结束后,ui变量不再使用,被释放,而user还是没有变,依然指向User对象。
结论:当传递方法参数类型为引用数据类型时,参数重新实例化,则修改的是新的对象的值。
2.3内部方法2个对象互换对象引用,这外部被引用的对象值变了
public static void main(String[] args) { UserInfo user1 = new UserInfo(); UserInfo user2 = new UserInfo(); user1 = new UserInfo(); user1.setId(1); user1.setName("张三1"); user2 = new UserInfo(); user2.setId(2); user2.setName("张三2"); System.out.println("=====copyUser4====="); System.out.println("user1: "+user1.getId()+" - "+user1.getName()); System.out.println("user2: "+user2.getId()+" - "+user2.getName()); copyUser4(user1, user2); System.out.println("user1: "+user1.getId()+" - "+user1.getName()); System.out.println("user2: "+user2.getId()+" - "+user2.getName()); } public static void copyUser4(UserInfo ui1,UserInfo ui2) { UserInfo tmp = ui2; ui2 = ui1; ui1 = tmp; ui1.setId(200); ui1.setName("李四"); ui2.setId(300); ui2.setName("王五"); System.out.println("ui1: "+ui1.getId()+" - "+ui1.getName()); System.out.println("ui2: "+ui2.getId()+" - "+ui2.getName()); }
结果
=====copyUser4===== user1: 1 - 张三1 user2: 2 - 张三2 ui1: 200 - 李四 ui2: 300 - 王五 user1: 300 - 王五 user2: 200 - 李四
分析:
1)ui1变量被初始化为user1值的拷贝,ui2变量被初始化为user2值的拷贝。
2)ui1重新指向user2,ui2重新指向user1。
3)ui1调用set赋值后,修改的是user2的值;ui2调用set赋值后,修改的是user1的值。
4)方法结束后,ui1和ui2变量不再使用,被释放,而user1(被ui2修改)和user2(被ui1修改)被响应修改。
结论:当传递方法参数类型为引用数据类型时,参数重新指向其他对象时,则修改的是新的对象的值。
参照下图
厉害厉害X2厉害X3 |
请输入有意义的内容,最多1000字,切勿灌水!博主将保留删除评论的权力![]~( ̄▽ ̄)~* |
请输入有意义的内容,最多1000字,切勿灌水!博主将保留删除评论的权力![]~( ̄▽ ̄)~* 请输入有意义的内容,最多1000字,切勿灌水!博主将保留删除评论的权力![]~( ̄▽ ̄)~* 请输入有意义的内容,最多1000字,切勿灌水!博主将保留删除评论的权力![]~( ̄▽ ̄)~* 请输入有意义的内容,最多1000字,切勿灌水!博主将保留删除评论的权力![]~( ̄▽ ̄)~* 请输入有意义的内容,最多1000字,切勿灌水!博主将保留删除评论的权力![]~( ̄▽ ̄)~* 请输入有意义的内容,最多1000字,切勿灌水!博主将保留删除评论的权力![]~( ̄▽ ̄)~* 请输入有意义的内容,最多1000字,切勿灌水!博主将保留删除评论的权力![]~( ̄▽ ̄)~* 请输入有意义的内容,最多1000字,切勿灌水!博主将保留删除评论的权力![]~( ̄▽ ̄)~* |
啊啊啊 啊 啊啊啊啊 啊 啊 啊 啊啊啊啊 啊 啊 啊 啊啊啊啊 啊 啊 啊 啊啊啊啊 啊 啊 啊 啊啊啊啊 啊 啊 啊 啊啊啊啊 啊 啊 啊 啊啊啊啊 啊 啊 啊 啊啊啊啊 啊 啊 啊 啊啊啊啊 啊 啊 啊 啊 啊 啊 啊 |
啊 啊 啊 啊 啊 |
这是加粗的文字 这是倾斜的文字 这是斜体加粗的文字