java字符串如何不可变?

时间:2015-01-31 12:36:28

标签: java string

我在java类中的方法中有一个字符串,如下所示

public void show(){
  String s1;
  s1 = "abc";
  s1 = "def";
  System.out.println(s1);
}

这里的输出是 def ,但由于String是不可变的,所以我不明白字符串s1在这里是不可变的,因为我可以从 abc 更改String s1内容 def

你可以让我理解这个吗?

4 个答案:

答案 0 :(得分:5)

你没有改变字符串;您更改了变量s1,以便它引用不同的字符串。原字符串" abc"仍然存在且尚未修改(并且无法修改,因为字符串是不可变的)。

试试这个:

public void show() {
    String s1 = "abc";
    String s2 = s1;
    System.out.println("s1 is same object is s2? = " + (s1 == s2));
    s1 = "def";
    System.out.println("s1 = " + s1);
    System.out.println("s2 = " + s2);
}

请注意,将s1设置为引用新字符串不会影响原始字符串,因此s2仍会引用它。

答案 1 :(得分:2)

通过可变,你的意思是你有相同的对象,你可以修改它的状态(就像你的类有一个Date对象)。因此,不可变的恰恰相反。考虑Date类,我将它定义为:

Date date = new Date();//print it and you will get today's date
date.setTime(date.getTime() - 10days in millis);//print and see you changed your date by bask 10 days which you changed internal state (field) of Date

现在在您的示例中,您将新的字符串重新分配给s1字符串,即将引用从一个字符串更改为另一个字符串。您没有更改内部字符数组,即String对象的字段。

答案 2 :(得分:2)

字符串 不可变表示您无法更改对象本身,但可以更改对象的引用。当你打电话

  s1 = "abc";
  s1 = "def";

,您实际上是将s1的引用更改为由字符串文字“def”创建的新对象。

S1只是对象的引用,它不是实际对象

String Constant Pool

试试这种方式

   s1="abc";
   s1.toUpperCase();
   System.out.println(s1);

输出仍然

   abc

由于s1.toUpperCase()而不是更改 String s1 的内容,它会创建一个带有大写内容的新对象,但由于我们没有捕获返回的变量这就是输出仍然相同的原因

现在尝试使用

   s1="abc";
   s1=s1.toUpperCase();
   System.out.println(s1);

现在输出

   ABC

答案 3 :(得分:0)

如果您尝试创建字符串对象。内存将在堆上以及字符串池中创建。例如:String str = new String(" hello"); 对于变量str,将在堆上创建值为" hello"以及字符串"你好"将在字符串池中创建。 str是引用变量,它将引用" hello"在字符串池中。 现在,如果您尝试创建

String s1 =" hello&#34 ;;

这里s1是引用变量.String pool已经有值" hello"。所以s1会引用"你好"。

与此概念相同。 s1是引用变量。它首先引用" abc"在String池。然后它指的是" def"在字符串池。你没有对" abc"做出任何改变。或" def"在字符串池,因为它们是不可变的。如果你想为StringBuffer和StringBuilder创建可变字符串。