为什么修改了 ArrayList 参数,而不是 String 参数?

public class StackOverFlow {
    public static void main(String[] args) {
        ArrayList<String> al = new ArrayList<String>();
        al.add("A");
        al.add("B");
        markAsNull(al);
        System.out.println("ArrayList elements are "+al);

        String str = "Hello";
        markStringAsNull(str);
        System.out.println("str "+ str);
    }
    private static void markAsNull(ArrayList<String> str){
        str.add("C");
        str= null;
    }
    private static void markStringAsNull(String str){
        str = str + "Append me";
        str = null;
    }
}

此输出:

ArrayList elements are [A, B, C]
str Hello

在 的情况下,添加的元素将被检索。如果方法调用对传递的字符串没有影响。JVM 到底在做什么?任何人都可以详细解释吗?ArrayListString


答案 1

在 Arraylist 字符串对象的情况下,添加的元素将被回收。对于 String,方法调用对正在传递的字符串没有影响。

发生这种情况的原因是Java是按值传递的,并且s是不可变的String

当您致电时

markAsNull(ArrayList<String> str)

将按名称为 同一指名创建新的引用。当您在其上的元素被添加到同一对象时。稍后,您放入,但该对象添加了新值,并由 指向。strArrayListaladdstrstrnulla1

当您致电时

markStringAsNull(String str)
{
    str = str + "Append me";
    // ...
}

该行通过追加给定的字符串来创建新对象,并将其分配给 。但同样,它只是对实际字符串的引用,现在指向新创建的字符串。(由于不可爱)并且原始字符串不会更改。str = str + "Append me";Stringstr


答案 2

这些方法将本地引用设置为 。这对存储在该位置的实际值没有影响。该方法仍然具有自己的对值的引用,并且可以使用这些值进行调用。markXAsNullnullmainprintln

此外,在执行字符串串联时,正在 Object 上调用,这就是为什么 ArrayList 输出为括号中其值的列表的原因。toString()