在阅读本文之前,根据自己的经验和理解,大家可以先思考并选择一下Java函数的参数传递方式:
A. 是按值传递的?
B. 按引用传递的?
C. 部分按值部分按引用?
此处暂不宣布正确答案,我们通过一个简单的例子让大家自己找答案:
1. 先定义一个类型Value
Java代码
1.public static class Value {
2. private String value = "value";
3. public String getValue() { return value; }
4. public void setValue(String value) { this.value = value; }
5.}
public static class Value {
private String value = "value";
public String getValue() { return value; }
public void setValue(String value) { this.value = value; }
}
2. 写两个函数newValue和modifyValue:newValue会将入参指向一个新的对象,modifyValue会调用入参的setValue方法修改对象的value值。
Java代码
1.public static void newValue(Value value) {
2. value = new Value();
3. value.setValue("new value");
4. System.out.println("In newValue, HashCode = " + value.hashCode() + ", value = " + value.getValue());
5.}
6.
7.public static void modifyValue(Value value) {
8. value.setValue("new value");
9. System.out.println("In modifyValue, HashCode = " + value.hashCode() + ", value = " + value.getValue());
10.}
public static void newValue(Value value) {
value = new Value();
value.setValue("new value");
System.out.println("In newValue, HashCode = " + value.hashCode() + ", value = " + value.getValue());
}
public static void modifyValue(Value value) {
value.setValue("new value");
System.out.println("In modifyValue, HashCode = " + value.hashCode() + ", value = " + value.getValue());
}
3. 简单的测试代码
Java代码
1.public static void main(String[] args) {
2. Value value1 = new Value();
3. System.out.println("Before modify, HashCode = " + value1.hashCode() + ", value = " + value1.getValue());
4. // 将value1指向新的Value对象
5. newValue(value1);
6. System.out.println("After modify, HashCode = " + value1.hashCode() + ", value = " + value1.getValue() + "\n");
7. Value value2 = new Value();
8. System.out.println("Before modify, HashCode = " + value2.hashCode() + ", value = " + value2.getValue());
9. // 使用object的set方法,修改对象的内部值
10. modifyValue(value2);
11. System.out.println("After modify, HashCode = " + value2.hashCode() + ", value = " + value2.getValue());
12.}
public static void main(String[] args) {
Value value1 = new Value();
System.out.println("Before modify, HashCode = " + value1.hashCode() + ", value = " + value1.getValue());
// 将value1指向新的Value对象
newValue(value1);
System.out.println("After modify, HashCode = " + value1.hashCode() + ", value = " + value1.getValue() + "\n");
Value value2 = new Value();
System.out.println("Before modify, HashCode = " + value2.hashCode() + ", value = " + value2.getValue());
// 使用object的set方法,修改对象的内部值
modifyValue(value2);
System.out.println("After modify, HashCode = " + value2.hashCode() + ", value = " + value2.getValue());
}
4. 执行结果日志:
Java代码
1.Before modify, HashCode = 12677476, value = value
2.In newValue, HashCode = 33263331, value = new value
3.After modify, HashCode = 12677476, value = value
4.
5.Before modify, HashCode = 6413875, value = value
6.In modifyValue, HashCode = 6413875, value = new value
7.After modify, HashCode = 6413875, value = new value
Before modify, HashCode = 12677476, value = value
In newValue, HashCode = 33263331, value = new value
After modify, HashCode = 12677476, value = value
Before modify, HashCode = 6413875, value = value
In modifyValue, HashCode = 6413875, value = new value
After modify, HashCode = 6413875, value = new value
5. 结果分析:
上述代码这是非常常见的一种编程模式:在外围定义|保存|获取一个值或对象,将这个对象作为参数传入一个方法,在方法中修改对象的属性、行为。但两个方法newValue和modifyValue的修改方式不一样,在方法调用之后,该对象在外围看来也有很大的差别!如何理解这种差异呢?先温故一下按值传递、按引用传递的概念:
* 按值传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的一个副本。因此,如果函数修改了该参数,仅改变副本,而原始值保持不变。
* 按引用传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的内存地址,而不是值的副本。因此,如果函数修改了该参数,参数的原始值(函数块之外的调用代码中)也随之改变。
|