java值传递和增强for循环问题
2023-02-15 14:59:17

Java是值传递

首先要理解 Java是值传递问题

正确理解:

  1. java 中只有值传递没有引用传递
  2. 对于基本数据类型传递的就是栈区中的值。
  3. 对于引用类型传递的也是栈区值只不过值是一个地址。

基本数据类型和引用数据类型

内存划分方式不同
-基本数据类型:值存储在栈区域
-byte short int long float double char boolean
-引用数据类型:值存储在堆区域
-class interface 数组

引用数据类型在栈区存储的值为对应堆空间的地址

形参与实参

形式参数:是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数。

实际参数:在调用有参函数时,主调函数和被调函数之间有数据传递关系。在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”。

实际参数是调用有参方法的时候真正传递的内容,而形式参数是用于接收实参内容的参数。

值传递和引用传递

值传递的特征——修改传递过来的值,并不会影响原来的对象

值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

引用传递是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

值传递和引用传递的区别是 实参到底有没有被复制一份给形参。

for each循环改数组元素值问题

for(元素类型 元素变量i : 遍历对象obj){ xxxxxx; }

元素变量 i 是一个局部变量,它是引用数组当前元素的副本(类似复制一份)

使用for each循环更改数组元素时,出现了未能成功改值问题

自定义Person类,有name(String)和age(int)两个属性。

1
2
3
4
int[] nums = { 1, 2, 3, 4, 5 };
String[] strs = { "aaa", "bbb", "ccc" };
Person[] persons = { new Person("熊大", 20), new Person("翠花", 17), new Person("熊二", 19) };

接下来

修改 int数组代表的基本数据类型的数组

1
2
3
4
5
6
7
8
9
10
11
12
for (int i : nums) {
if (i == 4) {
i = 72;
}
}
for (int i : nums) {
System.out.print(i + "\t");
}
System.out.println();
// 输出:1 2 3 4 5
// 说明nums数组并未修改

1
2
3
4
5
6
7
8
//相当于:
for(int j=0;j<nums.length;j++){
int i=nums[j];
if(i==4){
i=72;
}
//所以说修改对于原数组根本没有任何影响
}

修改用String类和Person类代表引用数据类型的数组

对于String类

1
2
3
4
5
6
7
8
9
10
11
for (String string : strs) {
if (string.equals("aaa")) {
string = "hello";
}
}
for (String string : strs) {
System.out.print(string + "\t");
}
System.out.println();
// 输出:aaa bbb ccc
// 说明str数组并未修改
1
2
3
4
5
6
7
8
9
10
//相当于
for (int j = 0; j < strs.length; j++) {
String i = strs[j];
if (i.equals("aaa")) {
i = "hello";
}
}
//String类有不可变的特征,对字符串的修改都是产生了新的字符串对象
//所以这里也没有任何影响
//输出:aaa bbb ccc

对于Person类

1
2
3
4
5
6
7
8
9
10
11
for (Person person : persons) {
if (person.name.equals("熊大")) {
person.age = 100;
}
}
for (Person person : persons) {
System.out.print(person + "\t");
}
// 输出:Person [name=熊大,age=100] Person [name=翠花,age=17] Person [name=熊二,age=19]
// 说明persons数组有修改
System.out.println();

但Java仍为值传递,对于对象参数,值的内容是对象的引用。

对于引用类型传递的也是栈区值,只不过值是一个地址。

1
2
3
4
5
6
7
8
//相当于
for(int x=0 ; x<persons.length ; x++) {
Person i=persons[x];
if (i.name.equals("熊大")) {
i.age = 100;
//这里改变的是persons[x].age,而不是persons[x]本身,所以能成功改变
}
}

证:通过调试(调试信息)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
persons ={Person[3]@500}

0 ={Person@494}"Person [name=熊大, age=20]“

1 ={Person@496)"Person [name=翠花, age=17]”

2 ={Person@498}"Person [name=熊二, age=19]“

x=0

i ={Person@494]"Person [name=熊大, age=20]"

persons[x] ={Person@494]"Person [name=熊大, age=20]"

i.age = 20

i.name ="熊大"

//经过更改
persons ={Person[3]@500}

0 ={Person@494}"Person [name=熊大, age=100]“

1 ={Person@496)"Person [name=翠花, age=17]”

2 ={Person@498}"Person [name=熊二, age=19]“

i={Person@494}"Person [name=熊大,age=100]"
2023-02-15 14:59:17