什么是值传递和引用传递?
值传递:
方法调用时,实际参数把它的值传递给对应的形式参数,函数接收的是原始值的一个copy,此时内存中存在两个相等的基本类型,即实际参数和形式参数,后面方法中的操作都是对形参这个值的修改,不影响实际参数的值。
引用传递:
也称为传地址。方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,函数接收的是原始值的内存地址;
在方法执行中,形参和实参内容相同,指向同一块内存地址,方法执行中对引用的操作将会影响到实际对象。
这里要特殊考虑String,以及Integer、Double等几个基本类型包装类,它们都是不可变的类型,
因为没有提供自身修改的函数,每次操作都是新生成一个对象,所以要特殊对待,可以认为是和基本数据类型相似,传值操作。
创建一个测试类:Test1
package test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Test1 {
public static void main(String[] args) {
//基本类型
int x = 10;
//特殊的引用类型 不可变的类型
String y = "张三";
//特殊的引用类型 不可变的类型
Integer z = 20;
//引用类型
List<String> perNumList = new ArrayList<>();
//引用类型
Map<String, Object> personMap = new HashMap<>();
personMap.put("num", "101");
personMap.put("name", "李四");
perNumList.add("胜多负少");
perNumList.add("AA");
System.out.println(
"调用方法之前:x=" + x + ";y=" + y + ";perNumList=" + perNumList + ";z=" + z + ";personMap=" + personMap);
print(x, y, perNumList, z, personMap);
System.out.println(
"调用方法之后:x=" + x + ";y=" + y + ";perNumList=" + perNumList + ";z=" + z + ";personMap=" + personMap);
}
/**
* @param x 基本类型 值传递
* @param y 特殊的引用类型 不可变的类型 值传递
* @param perNumList 引用类型 引用传递
* @param z 特殊的引用类型 不可变的类型 值传递
* @param personMap 引用类型 引用传递
*/
public static void print(int x, String y, List<String> perNumList, Integer z, Map<String, Object> personMap) {
x = x + 10;
y = "张三" + "****";
perNumList.remove(0);
z = 200;
personMap.put("num", "102");
personMap.put("name", "李四@@@@@@@@@");
System.out.println(
"调用方法中:x=" + x + ";y=" + y + ";perNumList=" + perNumList + ";z=" + z + ";personMap=" + personMap);
}
}
结果:
调用方法之前:x=10;y=张三;perNumList=[胜多负少, AA];z=20;personMap={num=101, name=李四}
调用方法中:x=20;y=张三****;perNumList=[AA];z=200;personMap={num=102, name=李四@@@@@@@@@}
调用方法之后:x=10;y=张三;perNumList=[AA];z=20;personMap={num=102, name=李四@@@@@@@@@}
结论:
(1)基本数据类型传值,对形参的修改不会影响实参;
(2)引用类型传引用,形参和实参指向同一个内存地址(同一个对象),所以对参数的修改会影响到实际的对象;
(3)String, Integer, Double等immutable的类型特殊处理,可以理解为传值,最后的操作不会修改实参对象。