Skip to content

Commit a15058a

Browse files
authored
修改表述错误:Java中有值传递和引用传递->Java中只有值传递
1 parent 71a7068 commit a15058a

File tree

1 file changed

+63
-109
lines changed

1 file changed

+63
-109
lines changed

面试必备/最最最常见的Java面试题总结/第一周(2018-8-7).md

Lines changed: 63 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
11

22

3-
## Java中的值传递和引用传递(非常重要)
3+
## 为什么 Java 中只有值传递?
44

5-
**首先要明确的是:“对象传递(数组、类、接口)是引用传递,原始类型数据(整型、浮点型、字符型、布尔型)传递是值传递。”**
65

7-
### 那么什么是值传递和应用传递呢?
6+
首先回顾一下在程序设计语言中有关将参数传递给方法(或函数)的一些专业术语。**按值调用(call by value)表示方法接收的是调用者提供的值,而按引用调用(call by reference)表示方法接收的是调用者提供的变量地址。一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值。** 它用来描述各种程序设计语言(不只是Java)中方法参数传递方式。
87

9-
**值传递**是指对象被值传递,意味着传递了对象的一个副本,即使副本被改变,也不会影响源对象。(因为值传递的时候,实际上是将实参的值复制一份给形参。)
8+
**Java程序设计语言总是采用按值调用。也就是说,方法得到的是所有参数值的一个拷贝,也就是说,方法不能修改传递给它的任何参数变量的内容。**
109

11-
**引用传递**是指对象被引用传递,意味着传递的并不是实际的对象,而是对象的引用。因此,外部对引用对象的改变会反映到所有的对象上。(因为引用传递的时候,实际上是将实参的地址值复制一份给形参。)
10+
**下面通过 3 个例子来给大家说明**
1211

13-
有时候面试官不是单纯问你“Java中是值传递还是引用传递”是什么啊,骚年?而是给出一个例子,然后让你写出答案,这种也常见在笔试题目中!所以,非常重要了,请看下面的例子:
12+
### example 1
1413

15-
### 值传递和应用传递实例
16-
17-
#### 1. 值传递
1814

1915
```java
2016
public static void main(String[] args) {
@@ -48,151 +44,109 @@ num2 = 20
4844

4945
**解析:**
5046

51-
在swap方法中,a、b的值进行交换,并不会影响到num1、num2。因为,a、b中的值,只是从num1、num2的复制过来的。
52-
也就是说,a、b相当于num1、num2的副本,副本的内容无论怎么修改,都不会影响到原件本身。
53-
54-
#### 2. 引用传递
55-
56-
```java
57-
public static void main(String[] args) {
58-
int[] arr = {1,2,3,4,5};
47+
![example 1 ](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-27/22191348.jpg)
5948

60-
change(arr);
49+
在swap方法中,a、b的值进行交换,并不会影响到 num1、num2。因为,a、b中的值,只是从 num1、num2 的复制过来的。也就是说,a、b相当于num1、num2 的副本,副本的内容无论怎么修改,都不会影响到原件本身。
6150

62-
System.out.println(arr[0]);
63-
}
51+
**通过上面例子,我们已经知道了一个方法不能修改一个基本数据类型的参数,而对象引用作为参数就不一样,请看 example2.**
6452

65-
public static void change(int[] array) {
66-
//将数组的第一个元素变为0
67-
array[0] = 0;
68-
}
69-
```
7053

71-
**结果:**
72-
73-
```
74-
1
75-
0
76-
```
77-
78-
**解析:**
79-
80-
无论是主函数,还是change方法,操作的都是同一个地址值对应的数组。 。因此,外部对引用对象的改变会反映到所有的对象上。
81-
82-
### 一些特殊的例子
83-
84-
#### 1. StringBuffer类型传递
54+
### example 2
8555

8656
```java
87-
// 测试引用传递:StringBuffer
88-
@org.junit.Test
89-
public void method1() {
90-
StringBuffer str = new StringBuffer("公众号:Java面试通关手册");
91-
System.out.println(str);
92-
change1(str);
93-
System.out.println(str);
57+
public static void main(String[] args) {
58+
int[] arr = { 1, 2, 3, 4, 5 };
59+
System.out.println(arr[0]);
60+
change(arr);
61+
System.out.println(arr[0]);
9462
}
9563

96-
public static void change1(StringBuffer str) {
97-
str = new StringBuffer("abc");//输出:“公众号:Java面试通关手册”
98-
//str.append("欢迎大家关注");//输出:公众号:Java面试通关手册欢迎大家关注
99-
//str.insert(3, "(编程)");//输出:公众号(编程):Java面试通关手册
100-
64+
public static void change(int[] array) {
65+
// 将数组的第一个元素变为0
66+
array[0] = 0;
10167
}
10268
```
10369

10470
**结果:**
10571

10672
```
107-
公众号:Java面试通关手册
108-
公众号:Java面试通关手册
73+
1
74+
0
10975
```
11076

11177
**解析:**
11278

79+
![example 2](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-27/3825204.jpg)
11380

114-
很多要这个时候要问了:StringBuffer创建的明明也是对象,那为什么输出结果依然是原来的值呢?
115-
116-
因为在`change1`方法内部我们是新建了一个StringBuffer对象,所以`str`指向了另外一个地址,相应的操作也同样是指向另外的地址的。
81+
array 被初始化 arr 的拷贝也就是一个对象的引用,也就是说 array 和 arr 指向的时同一个数组对象。 因此,外部对引用对象的改变会反映到所对应的对象上。
11782

118-
那么,如果将`change1`方法改成如下图所示,想必大家应该知道输出什么了,如果你还不知道,那可能就是我讲的有问题了,我反思(开个玩笑,上面程序中已经给出答案):
11983

120-
```
121-
public static void change1(StringBuffer str) {
84+
**通过 example2 我们已经看到,实现一个改变对象参数状态的方法并不是一件难事。理由很简单,方法得到的是对象引用的拷贝,对象引用及其他的拷贝同时引用同一个对象。**
12285

123-
str.append("欢迎大家关注");
124-
str.insert(3, "(编程)");
125-
126-
}
127-
```
86+
**很多程序设计语言(特别是,C++和Pascal)提供了两种参数传递的方式:值调用和引用调用。有些程序员(甚至本书的作者)认为Java程序设计语言对对象采用的是引用调用,实际上,这种理解是不对的。由于这种误解具有一定的普遍性,所以下面给出一个反例来详细地阐述一下这个问题。**
12887

12988

130-
#### 2. String类型传递
89+
### example 3
13190

13291
```java
133-
// 测试引用传递:Sring
134-
@org.junit.Test
135-
public void method2() {
136-
String str = new String("公众号:Java面试通关手册");
137-
System.out.println(str);
138-
change2(str);
139-
System.out.println(str);
140-
}
92+
public class Test {
14193

142-
public static void change2(String str) {
143-
// str="abc"; //输出:公众号:Java面试通关手册
144-
str = new String("abc"); //输出:公众号:Java面试通关手册
94+
public static void main(String[] args) {
95+
// TODO Auto-generated method stub
96+
Student s1 = new Student("小张");
97+
Student s2 = new Student("小李");
98+
Test.swap(s1, s2);
99+
System.out.println("s1:" + s1.getName());
100+
System.out.println("s2:" + s2.getName());
145101
}
146102

103+
public static void swap(Student x, Student y) {
104+
Student temp = x;
105+
x = y;
106+
y = temp;
107+
System.out.println("x:" + x.getName());
108+
System.out.println("y:" + y.getName());
109+
}
110+
}
147111
```
148112

149113
**结果:**
150114

151115
```
152-
公众号:Java面试通关手册
153-
公众号:Java面试通关手册
116+
x:小李
117+
y:小张
118+
s1:小张
119+
s2:小李
154120
```
155121

156-
可以看到不论是执行`str="abc;"`还是`str = new String("abc");`str的输出的值都不变。
157-
按照我们上面讲“StringBuffer类型传递”的时候说的,`str="abc;"`应该会让str的输出的值都不变。为什么呢?因为String在创建之后是不可变的。
122+
**解析:**
158123

159-
#### 3. 一道类似的题目
124+
交换之前:
160125

161-
下面的程序输出是什么?
162-
```java
163-
public class Demo {
164-
public static void main(String[] args) {
165-
Person p = new Person("张三");
126+
![](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-27/88729818.jpg)
166127

167-
change(p);
128+
交换之后:
168129

169-
System.out.println(p.name);
170-
}
130+
![](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-27/34384414.jpg)
171131

172-
public static void change(Person p) {
173-
Person person = new Person("李四");
174-
p = person;
175-
}
176-
}
177132

178-
class Person {
179-
String name;
133+
通过上面两张图可以很清晰的看出: **方法并没有改变存储在变量 s1 和 s2 中的对象引用。swap方法的参数x和y被初始化为两个对象引用的拷贝,这个方法交换的是这两个拷贝**
180134

181-
public Person(String name) {
182-
this.name = name;
183-
}
184-
}
185-
```
186-
很明显仍然会输出`张三`。因为`change`方法中重新创建了一个`Person`对象。
135+
### 总结
187136

188-
那么,如果把` change`方法改为下图所示,输出结果又是什么呢?
137+
Java程序设计语言对对象采用的不是引用调用,实际上,对象引用是按
138+
值传递的。
189139

190-
```java
191-
public static void change(Person p) {
192-
p.name="李四";
193-
}
194-
```
195-
答案我就不说了,我觉得大家如果认真看完上面的内容之后应该很很清楚了。
140+
下面再总结一下Java中方法参数的使用情况:
141+
142+
- 一个方法不能修改一个基本数据类型的参数(即数值型或布尔型》
143+
- 一个方法可以改变一个对象参数的状态。
144+
- 一个方法不能让对象参数引用一个新的对象。
145+
146+
147+
### 参考:
148+
149+
《Java核心技术卷Ⅰ》基础知识第十版第四章4.5小节
196150

197151
## 二 ==与equals(重要)
198152

0 commit comments

Comments
 (0)