Java值传递和引用传递及形参实参的分析(实例对比c++)
来源:互联网 发布:ubuntu debian 编辑:程序博客网 时间:2024/05/29 19:06
一. 先看看C++的一个实例(方便理解Java)
1. 例子argtest.cpp中的swap1函数是最常见的一种,形参copy了一份实参,也即main中的a1_1和swap1中的a1_1在内存中是两份不同的数据,但传入时它们保存的值是相等的,仅此而已,所以你在swap1函数中怎么捣鼓a1_1,都不会影响到main中的a1_1;
Java基本类型的参数传入,即int、boolean、char等,可以理解成这种方法,也就是所谓的“值传递”;
2. 例子argtest.cpp中的swap2函数,其实int换成某个class也同样适用,你可以swap2中的“int *a1_2” 脑补成 "User *user1"也是完全没问题的;
swap2是用指针传递参数,尽管如此,和swap1本质上也是一样的:“指针”也是数据,所以swap2的a1_2即形参,也是copy了一份实参,只不过这次实参是指针,但传入时它们保存的值是相等的,也就是指向的内存是同一份。也仅此而已,实参和形参依旧是2份不同的东东,所以在swap2那样“你等于我我等于你”是起不到作用的;要想起作用就得用到C/C++的取值符“ * ”(星号);
Java引用类型的参数擦混入,可以理解成这种方式,也就是所谓的“引用传递”,其中Java的引用直接看做“指针”;(其实我感觉本质依旧是值传递)
3. 例子argtest.cpp中的swap3函数,用到了c++的引用方法,本质其实也是传入了指针;
要明确的是:Java没有swap3这种方式,还需要注意的是,Java的引用和c++的引用是两回事,不要搞混了;本文针对的是Java,所以此方式不赘述;
argtest.cpp:
#include <iostream>using namespace std;void swap1(int a1_1, int a2_1) { int temp = 0; temp = a1_1; a1_1 = a2_1; a2_1 = temp;}void swap2(int *a1_2, int *a2_2) { int *temp = 0; temp = a1_2; a1_2 = a2_2; a2_2 = temp;}void swap3(int &a1_3, int &a2_3) { int temp = 0; temp = a1_3; a1_3 = a2_3; a2_3 = temp;}int main(){ int a1_1 = 1; int a2_1 = 2; int a1_2 = 1; int a2_2 = 2; int a1_3 = 1; int a2_3 = 2; swap1(a1_1, a2_1); cout<<a1_1<<" "<<a2_1; //输出结果: 1 2 cout<<"\n"; swap2(&a1_2, &a2_2); cout<<a1_2<<" "<<a2_2; //输出结果: 1 2 cout<<"\n"; swap3(a1_3, a2_3); cout<<a1_3<<" "<<a2_3; //输出结果: 2 1 cout<<"\n";}
二. Java的形参和实参
1. 对比前后2个例子的前2个方法,你或许可以找到很多共同点,我认为前者的swap1对应后者的swap1,前者的swap2对应后者的swapUser;
2. 不管传入方法的是基本类型还是引用类型,形参和实参都是两份数据,只不过“存的内容”一样而已;
3. 传入引用其实可以理解为传入的是"指针",引用形参和引用实参是两份“指针”,只不过它们指向同一份数据;
4. ArgTest.java中的swapUserAge方法之所以能够成功交换数据,因为“u1.age”表示的是形参指向的数据,而不是形参本身,形参和实参虽然是两份数据,但是它们指向的数据是同一份的,所以“看起来是修改了”。其实swapUserAge中依旧无法改变main中栈里面的那个实参user1,改变的只是user1指向的那份堆内存;
ArgTest.java:
public class ArgTest { public static void main(String[] args) { int a1 = 1; int a2 = 2; swap1(a1, a2); System.out.println(a1 + " " + a2); //输出结果: 1 2 User user1 = new User(1); User user2 = new User(2); swapUser(user1, user2); System.out.println(user1.age); //输出结果: 1 swapUserAge(user1, user2); System.out.println(user1.age); //输出结果: 2 } private static void swap1(int a1, int a2) { int temp; temp = a1; a1 = a2; a2 = temp; } private static void swapUser(User u1, User u2) { User temp; temp = u1; u1 = u2; u2 = temp; } private static void swapUserAge(User u1, User u2) { int tempAge = u1.age; u1.age = u2.age; u2.age = tempAge; }}class User { public int age; public String name; public User(int age) { this.age = age; } public void showUser() { System.out.println("I am User"); }}
三. Java的值类型数据和引用类型数据
引用王垠的一句话:
"实际上,所有的数据都是引用类型就是 Scheme 和 Java 最初的设计原理。原始类型用值来传递数据只是一种性能优化(叫做 inlining),它对于程序员应该是透明(看不见)的。那些在面试时喜欢问“Java 是否所有数据都是引用”,然后当你回答“是”的时候纠正你说“int,boolean 是值类型”的人,都是本本主义者。"
我认为他说的很有道理,感兴趣的可以点进去看一下他那篇博文,写得非常不错。
- Java值传递和引用传递及形参实参的分析(实例对比c++)
- 值传递、引用传递和形参、实参
- 值传递和地址传递 实参和形参
- Java的值传递和引用传递
- java的引用传递和值传递
- java的引用传递和值传递
- Java的引用传递和值传递
- java的值传递和引用传递
- java的值传递和引用传递
- java的值传递和引用传递
- 传递给const引用形参的实参要求
- 形参和实参值单向的值传递
- [研究]引用实参的传递
- Java中值传递和引用传递实例
- Java--传参的值传递和引用传递问题
- Java的参数传递有值传递和引用传递
- java引用传递和c地址传递
- 深入分析java值传递和引用传递?
- Discuz! 7.2的exploit
- 搭建一个微服务框架所需要哪些技术(spring-cloud)
- Hdu2033 人见人爱A+B
- 嵌入式Linux启动过程
- 虚析构函数
- Java值传递和引用传递及形参实参的分析(实例对比c++)
- VIM 的状态行(statusline)设置
- 传统动画Animation的四种基础动画的使用
- 高吞吐量分布式系统kafka
- win10锁屏状态闹钟提示设置
- 墨刀使用总结
- 十,Future设计模式
- c语言基础(三)指针篇
- Git工具安装&项目发布Github