最近在工作中踩到了一個(gè)坑,就是Java的值傳遞和引用傳遞赌髓。對于值傳遞和引用傳遞定義有了解,但編寫代碼時(shí)沒有特別注意催跪。因?yàn)檫@個(gè)原因?qū)е乱粋€(gè)重大的線上bug锁蠕,這個(gè)是不可原諒的。由此決定把這些內(nèi)容再次牢記懊蒸,記錄下來荣倾。
作為一個(gè)工作幾年還犯這個(gè)錯(cuò)誤真是太慚愧!骑丸!
定義
- 傳值
傳遞的是值的副本舌仍。方法中對副本的修改,不會(huì)影響到調(diào)用方 - 傳引用:
傳遞的是引用的副本通危,共用一個(gè)內(nèi)存铸豁,會(huì)影響到調(diào)用方。
此時(shí)黄鳍,形參和實(shí)參指向同一個(gè)內(nèi)存地址推姻。
對引用副本本身(對象地址)的修改平匈,如設(shè)置為null框沟,重新指向其他對象藏古,不會(huì)影響到調(diào)用方。
基本數(shù)據(jù)類型
public class ParamChangeValue {
public static void main(String[] args) {
int s = 1;
System.out.println("args = [" + s + "]");
change(s);
System.out.println("args = [" + s + "]");
}
private static void change(int i){
i = i* 5;
}
}
輸出
args = [1]
args = [1]
對象
public class ObjectChangeValue {
public static class Score{
private int value;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
public static void main(String[] args) {
Score score = new Score();
score.setValue(1);
System.out.println("args = [" + score.getValue() + "]");
change(score);
System.out.println("after args = [" + score.getValue() + "]");
}
private static void change(Score score){
score.setValue(2);
}
}
輸出
args = [1]
after args = [2]
注:
如果對象被重新創(chuàng)建或賦值為null忍燥,即new則會(huì)重新指向其他對象拧晕,不影響其遠(yuǎn)對象的值
public class ObjectChangeValue {
public static class Score{
private int value;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
public static void main(String[] args) {
Score score = new Score();
score.setValue(1);
System.out.println("args = [" + score.getValue() + "]");
change(score);
System.out.println("after args = [" + score.getValue() + "]");
}
private static void change(Score score){
score = new score();
}
}
輸出
args = [1]
after args = [1]
String、Integer梅垄、Long等
public class StringChangeValue {
public static void main(String[] args) {
String s = "test1";
System.out.println("args = [" + s + "]");
change(s);
System.out.println("args = [" + s + "]");
}
private static void change(String i){
i = i + " test value";
}
}
輸出
args = [test1]
args = [test1]
總結(jié)
- 基本類型(byte,short,int,long,double,float,char,boolean)為傳值
- 對象類型(Object,數(shù)組厂捞,容器)為傳引用
- String、Integer队丝、Double等immutable類型因?yàn)轭惖淖兞吭O(shè)為final屬性靡馁,無法被修改,只能重新賦值或生成對象机久。
當(dāng)Integer作為方法參數(shù)傳遞時(shí)臭墨,對其賦值會(huì)導(dǎo)致原有的引用被指向了方法內(nèi)的棧地址,失去原有的的地址指向膘盖,所以對賦值后的Integer做任何操作都不會(huì)影響原有值胧弛。