今天在公司做的一個訂購成功后發(fā)送給用戶的郵件時,見到了之前別人留下來的一個問題措左。類似于下面這樣的代碼:
public class Test {
public static void test(List<Person> persons) {
Map<String,Person> map = new HashMap<>();
//把name相同的person合并依痊,age相加
for (Person person : persons) {
if(map.containsKey(person.getName())) {
Person person1 = map.get(person.getName());
person1.setAge(person.getAge() + person1.getAge());
} else {
map.put(person.getName(),person);
}
}
Collection<Person> values = map.values();
//這個persons指向新new的一個對象
persons = new ArrayList<>(values);
System.out.println(persons.toString());//-->[Person{name='s1', age='8'}]
}
public static void main(String[] args){
ArrayList<Person> persons = new ArrayList<>();
persons.add(new Person("s1",5));
persons.add(new Person("s1",3));
test(persons);
System.out.println(persons);//-->[Person{name='s1', age='8'}, Person{name='s1', age='3'}]
}
}
- main函數(shù)中外部有一個persons對象,傳入test函數(shù)中怎披,test函數(shù)中又把persons指向了一個新的對象胸嘁,for循環(huán)中直接操作了persons中的對象×构洌看下代碼中的輸出性宏,persons的打印方法內(nèi)外不一樣。
下面的例子清晰點(diǎn):
public class Test2 {
public static void setValue(String str){
str = "ss";
}
public static void setValue(Man str){
str = new Man("test");
}
public static class Man{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Man(String name) {
this.name = name;
}
@Override
public String toString() {
return "Man{" +
"name='" + name + '\'' +
'}';
}
}
public static void main(String[] args) {
String str = "s";
setValue(str);
System.out.println(str);
Man man = null;
setValue(man);
System.out.println(man);
}
}
上面代碼輸出:
s
null
原因是方法在執(zhí)行的時候有棧幀的概念状飞,入棧的時候只是壓棧,方法參數(shù)是傳入?yún)?shù)的副本毫胜。
基本類型:值存放在局部變量表中,無論如何修改只會修改當(dāng)前棧幀的值诬辈,方法執(zhí)行結(jié)束對方法外不會做任何改變酵使;此時需要改變外層的變量,必須返回主動賦值焙糟。
引用數(shù)據(jù)類型:指針存放在局部變量表中凝化,調(diào)用方法的時候,副本引用壓棧酬荞,賦值僅改變副本的引用搓劫。但是如果直接改變副本引用的值瞧哟,修改了引用地址的對象,此時方法以外的引用此地址對象當(dāng)然被修改枪向。(兩個引用勤揩,同一個地址,任何修改行為2個引用同時生效)
比如
public static void setValue(StringBuilder str){
str = new StringBuilder("sss");
}
public static void setValue2(StringBuilder str){
str.append("sss");
}
public static void main(String[] args) {
StringBuilder str = new StringBuilder();
setValue(str);
System.out.println(str.toString()); //輸出空字符串
setValue2(str);
System.out.println(str.toString()); //輸出sss
}
關(guān)于String秘蛔,本質(zhì)是final類型char數(shù)組陨亡,不可修改,只能賦值深员,在做參數(shù)傳入方法修改時负蠕,其實(shí)是新建對象,必須返回重新對外面的變量賦值才會對外面的String引用生效倦畅。
原文鏈接:https://blog.csdn.net/fenglllle/article/details/81389286