6

嗨,我正在为我的 scja 考试而学习,并且有一个关于通过 ref/value 传递的字符串以及它们如何不可变的问题。以下代码输出“abc abcfg”。

我想知道为什么会这样?我不明白方法 f 内部发生了什么。字符串是按值传递的,所以它肯定应该在方法内更改为“abcde”吗?因为如果 b+="fg" 附加到字符串,为什么它在方法内不起作用?

谢谢!

public class Test {

    public static void main(String[] args){
        String a =new String("abc");
        String b = a;
        f(b);
        b+="fg"
        System.out.println(a + " " + b);
    }

    public static void f(String b){
        b+="de";
        b=null;
    }
}
4

5 回答 5

8

b+="de";函数中的行void f(String b)创建了一个全新的对象,String该对象不会影响main函数中的对象。

因此,当我们说不可变String时,意味着对对象的任何更改都将导致创建一个全新的对象StringString

public class Test {
    public static void main(String[] args){
        String a =new String("abc");

        String b = a; // both a & b points to the same memory address

        f(b); // has no effect

        // b still has the value of "abc"
        b+="fg" // a new String object that points to different location than "a"

        System.out.println(a + " " + b); // should print "abc abcfg" 
    }

 public static void f(String b){
    b+="de";  // creates a new object that does not affect "b" variable in main
    b=null;
 }
}
于 2013-02-17T00:01:33.090 回答
3

在您的方法f()中,您正在为参数分配一个新的 String b,但参数就像局部变量一样,因此为它们分配一些东西对方法之外的任何东西都没有影响。这就是为什么你传入的字符串在方法调用之后没有改变的原因。

于 2013-02-17T00:00:20.093 回答
3

这行代码:

b += "de";

大致翻译为:

b = b + "de";

它创建了一个新字符串并将其存储在局部变量“b”中。无论如何,方法外的引用都不会因此而改变。在尝试理解这种方式如何/为什么这样工作时,需要记住几件关键的事情。

  1. 在 Java 中,所有方法参数都是按值传递的。
  2. 方法有一个本地堆栈,其中存储了所有数据,包括方法参数。

当您将新对象分配给传递给方法的变量时,您只是将本地堆栈中的地址替换为创建的新对象的地址。方法之外的实际对象地址保持不变。

于 2013-02-17T00:02:06.460 回答
0

当您将 String 传递给方法时,它会在方法中创建一个新的 String 对象。如果您在方法中添加 println 语句,如下所示:

public static void f(String b){
    b+="de";
    System.out.println(b);
    b=null;
}

您将看到输出“abcde”。

但是,一旦您退出该方法,您就会回到未更改的原始对象。因此,将 fg 附加到它只会产生一个包含“abcfg”的新字符串 (b)。

于 2013-02-17T00:01:10.963 回答
0

当您说 b+="de" 之类的内容时,您创建了一个新的 String 对象

就像说 b = new String(b+"de");

如果您真的想保留传入的值,请使用这样的 stringBuilder:

    StringBuilder a =new StringBuilder("abc");
        StringBuilder b = a;
        f(b);
        b.append("fg");
        System.out.println(a + " " + b);
    }

  public static void f(StringBuilder b){
        b.append("de");
        b=null;
    }

现在您的输出将是“abcdefg”,因为 stringbuilder 对象 b 已作为对象本身的值传递给 f。我修改了值,但没有使用“new”来指向另一个对象。希望现在清楚。

于 2016-10-05T20:04:33.273 回答