网站首页 > java教程 正文
在开始之前,我们首先需要搞懂如下的两个概念。
- 什么是形参与实参?
- 什么是值传递?什么是引用传递?
形参与实参
在Java方法的定义可能会用到参数的传入操作,在参数的定义中又可以分为如下的两种
实参(实际参数):用于传递给函数或者是方法的参数,它必须要有确定的值。
形参(形式参数):用户定义函数或者方法,用户接收实际参数,所以不需要有确定的值。
如下代码所示
String hello = "Hello!";
// hello 为实参
sayHello(hello);
// str 为形参
void sayHello(String str) {
System.out.println(str);
}
值传递与应用传递
在编程语言中将实际参数传递给具体的方法调用或者是某个函数的方式一般分为如下的两种。
- 值传递:方法接收到的实际参数的值的拷贝,会创建一个副本对象进行使用。
- 引用传递:方法接收到的直接是实际参数在堆中的应用地址,不会创建对象副本,对于参数值的修改会直接影响到实际参数的堆中的值
在其他的编程语言中,提供了两种参数传递方式,但是在Java语言中只是提供了值传递这一种方式。
为什么Java语言只有值传递?
传递基本类型的参数
public static void main(String[] args) {
int num1 = 10;
int num2 = 20;
swap(num1, num2);
System.out.println("num1 = " + num1);
System.out.println("num2 = " + num2);
}
public static void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
System.out.println("a = " + a);
System.out.println("b = " + b);
}
在上述代码中,swap()方法中对a和b二者的值进行了交换,并不会影响到num1和num2的值,因为a、b的值是从num1和num2进行了复制,也就是说a、b相当于num1和num2的副本。而且这个副本的内容无论如何修改,都不会影响到原来的值。
通过上面的例子我们知道,一个方法调用不修改一个基本数据类型的参数,如果采用对象引用作为参数就不一样了。
传递引用类型参数
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 };
System.out.println(arr[0]);
change(arr);
System.out.println(arr[0]);
}
public static void change(int[] array) {
// 将数组的第一个元素变为0
array[0] = 0;
}
上面代码输出结果如下
1
0
根据上面的代码来分析,可能有人会觉得Java对引用类型的参数采用的是引用传递。也就是将引用进行了复制,但是实际上,并不是这样,这里的传递的还是值传递。只不过这里传递的值是实际参数的地址。
也就是说change方法的参数拷贝的是arr实际参数的地址,所以参数与arr指向的是同一个数据对象,也就是说在方法内部对于形参的修改会影响到实际参数的值。下面我们就来根据下一个例子来介绍一下。
public class Person {
private String name;
// 省略构造函数、Getter&Setter方法
}
public static void main(String[] args) {
Person xiaoZhang = new Person("小张");
Person xiaoLi = new Person("小李");
swap(xiaoZhang, xiaoLi);
System.out.println("xiaoZhang:" + xiaoZhang.getName());
System.out.println("xiaoLi:" + xiaoLi.getName());
}
public static void swap(Person person1, Person person2) {
Person temp = person1;
person1 = person2;
person2 = temp;
System.out.println("person1:" + person1.getName());
System.out.println("person2:" + person2.getName());
}
上面代码执行结果如下
person1:小李
person2:小张
xiaoZhang:小张
xiaoLi:小李
分析代码会知道,两个引用类型的参数互换,并没有影响的实际参数?这是为什么呢?swap 方法的参数 person1 和 person2 只是拷贝的实参 xiaoZhang 和 xiaoLi 的地址。因此, person1 和 person2 的互换只是拷贝的两个地址的互换罢了,并不会影响到实参 xiaoZhang 和 xiaoLi 。所以两个参数相互交换并没有影响到实际的对内存中的数据。
引用传递是怎么样的?
到这里,我们就明白了在Java中只有值传递,而没有引用传递。但是对于引用传递大家还是很好奇,下面我们就通过一个简单的C++的代码来分析一下引用传递到底如何?
#include <iostream>
void incr(int& num)
{
std::cout << "incr before: " << num << "\n";
num++;
std::cout << "incr after: " << num << "\n";
}
int main()
{
int age = 10;
std::cout << "invoke before: " << age << "\n";
incr(age);
std::cout << "invoke after: " << age << "\n";
}
运行结果如下
invoke before: 10
incr before: 10
incr after: 11
invoke after: 11
从上面代码可以看出,在使用 incr 函数中对传入的形参进行了修改,并且对于形参的修改影响到了实参的值。这里需要注意的是 incr 形参的数据类型用的是 int& 才为引用传递,也就是将这个地址给到了操作参数,这个时候其操作的值就变成了引用所指的地址。但是如果是用 int 的话则还是值传递。
为什么Java不使用引用传递呢?
引用传递看似非常完美,并且能在方法内部就把实际参数值进行修改,但是在Java中还是没有采用引用传递。其实理由很简单,就是为了安全,因为在Java语言中对于对象的封装都是比较安全的,如果采用了引用传递,则传递的值就会影响到对象内部封装的方法,这个时候如果想再次使用该对象的话就会获取到原来的数据,这样对于对象封装是极不安全的。
猜你喜欢
- 2024-11-11 挨个举例子告诉你Java中的参数传递,我就不信你还不明白了
- 2024-11-11 Java值传递机制(java传值方式)
- 2024-11-11 Stack Overflow上188W+程序员都关注的问题
- 2024-11-11 为什么说Java不存在引用传递?(javax不存在)
- 2024-11-11 一份2021年的java面试题(java常见面试题)
- 2024-11-11 互联网大厂面试系列-为什么说在Java方法参数调用只有值传递呢?
- 2024-11-11 一文搞懂参数传递原理(参数传递的三种方式)
- 2024-11-11 Java程序员想年后跳槽,对JVM没有深入的理解,我劝你还是别跳了
- 2024-11-11 JAVA校招题基础知识点复习第二天(引用传递的本质是什么?)
- 2024-11-11 16、一个对象被当做参数传递给一个方法,这是值传递还是引用传递
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)