Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 47 additions & 4 deletions docs/java/basis/why-there-only-value-passing-in-java.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ tag:

方法的定义可能会用到 **参数**(有参的方法),参数在程序语言中分为:

- **实参(实际参数)** :用于传递给函数/方法的参数,必须有确定的值。
- **形参(形式参数)** :用于定义函数/方法,接收实参,不需要有确定的值。
- **实参(实际参数,Arguments)** :用于传递给函数/方法的参数,必须有确定的值。
- **形参(形式参数,Parameters)** :用于定义函数/方法,接收实参,不需要有确定的值。

```java
String hello = "Hello!";
Expand Down Expand Up @@ -112,7 +112,7 @@ num2 = 20

实际上,并不是的,这里传递的还是值,不过,这个值是实参的地址罢了!

也就是说 `change` 方法的参数拷贝的是 `arr` (实参)的地址,因此,它和 `arr` 指向的是同一个数组对象。这也就说明了为什么方法内部对形参的修改会影响到实参。
也就是说 `change` 方法的参数拷贝的是 `arr` (实参)的地址,因此,它和 `arr` 指向的是同一个数组对象。这也就说明了为什么方法内部对形参的修改会影响到实参。

为了更强有力地反驳 Java 对引用类型的参数采用的不是引用传递,我们再来看下面这个案例!

Expand Down Expand Up @@ -158,6 +158,47 @@ xiaoLi:小李

![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/java/basis/java-value-passing-03.png)

## 引用传递是怎么样的?

看到这里,相信你已经知道了 Java 中只有值传递,是没有引用传递的。
但是,引用传递到底长什么样呢?下面以 `C++` 的代码为例,让你看一下引用传递的庐山真面目。

```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 官方:**
1. 出于安全考虑,方法内部对值进行的操作,对于调用者都是未知的(把方法定义为接口,调用方不关心具体实现)。你也想象一下,如果拿着银行卡去取钱,取的是 100,扣的是 200,是不是很可怕。
2. Java 之父 James Gosling 在设计之处就看到了 C、C++ 的许多弊端,所以才想着去设计一门新的语言 Java。在他设计 Java 的时候就遵循了简单易用的原则,摒弃了许多开发者一不留意就会造成问题的“特性”,语言本身的东西少了,开发者要学习的东西也少了。

## 总结

Java 中将实参传递给方法(或函数)的方式是 **值传递** :
Expand All @@ -168,4 +209,6 @@ Java 中将实参传递给方法(或函数)的方式是 **值传递** :
## 参考

- 《Java 核心技术卷 Ⅰ》基础知识第十版第四章 4.5 小节
- [Java 到底是值传递还是引用传递? - Hollis的回答 - 知乎](https://www.zhihu.com/question/31203609/answer/576030121)
- [Java 到底是值传递还是引用传递? - Hollis的回答 - 知乎](https://www.zhihu.com/question/31203609/answer/576030121)
- [Oracle Java Tutorials - Passing Information to a Method or a Constructor](https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html)
- [Interview with James Gosling, Father of Java](https://mappingthejourney.com/single-post/2017/06/29/episode-3-interview-with-james-gosling-father-of-java/)