java中的可变和不可变String之间有什么区别

问题描述 投票:43回答:10

据我所知,

可以更改可变字符串,并且不能更改不可变字符串。

在这里,我想像这样更改String的值,

String str="Good";
str=str+" Morning";

和其他方式是,

StringBuffer str= new StringBuffer("Good");
str.append(" Morning");

在这两种情况下,我试图改变str的价值。任何人都可以告诉我,这两种情况有什么不同,并给我清晰的可变和不可变对象的图片。

java string immutability mutable stringbuffer
10个回答
83
投票

情况1:

String str = "Good";
str = str + " Morning";

在上面的代码中,您将创建3个String对象。

  1. “好”它进入字符串池。
  2. “早上”它也会进入字符串池。
  3. 通过连接“好”和“早晨”创造的“早安”。这家伙继续堆。

注意:字符串总是不可变的。没有,像一个可变的字符串。 str只是一个参考,最终指向“早安”。你实际上,没有在1对象上工作。你有3独特的String对象。


案例2:

StringBuffer str = new StringBuffer("Good"); 
str.append(" Morning");

StringBuffer包含一系列字符。它与String不同。上面的代码将字符添加到现有数组中。实际上,StringBuffer是可变的,其String表示不是。


0
投票

Mutable意味着您将保存对变量的相同引用并更改其内容但不可变您不能更改内容但您将声明新引用包含变量的旧值和旧值

Ex Immutable - > String

String x = "value0ne";// adresse one x += "valueTwo"; //an other adresse {adresse two} adresse关于堆内存的变化。

Mutable - > StringBuffer - StringBuilder StringBuilder sb = new StringBuilder(); sb.append("valueOne"); // adresse One sb.append("valueTwo"); // adresse One

我仍然在同一个地方,我希望这个评论有所帮助


11
投票

java中的可变和不可变String之间有什么区别

不可变的存在,可变的不存在。


8
投票

在Java中,所有字符串都是不可变的。当你试图修改String时,你真正在做的是创建一个新的。但是,当您使用StringBuilder时,实际上是在修改内容,而不是创建新内容。


5
投票

Java Strings是不可变的。

在您的第一个示例中,您正在更改对String的引用,从而为其分配两个其他Strings组合的值:str + " Morning"

相反,可以通过其方法修改StringBuilderStringBuffer


3
投票

当你说str时,你应该小心你的意思:

  • 你的意思是变量str
  • 或者你的意思是str引用的对象?

在你的StringBuffer例子中,你没有改变str的值,在你的String例子中,你没有改变String对象的状态。

体验差异的最痛苦的方式是这样的:

static void change(String in) { 
  in = in + " changed";
}

static void change(StringBuffer in) {
  in.append(" changed");
}

public static void main(String[] args) {
   StringBuffer sb = new StringBuffer("value");
   String str = "value";
   change(sb);
   change(str);
   System.out.println("StringBuffer: "+sb);
   System.out.println("String: "+str);
}

3
投票

Java中的字符串是不可变的。然而,在编程上下文中可变的意思是第一个问题。考虑下课,

public class Dimension {
    private int height;

    private int width;

    public Dimenstion() {
    }

    public void setSize(int height, int width) {
        this.height = height;
        this.width = width;
    }

    public getHeight() {
        return height;
    }

    public getWidth() {
        return width;
    }
}

现在在创建了Dimension的实例后,我们总是可以更新它的属性。注意,如果在其他意义状态中的任何属性可以更新为该类的实例,那么它被认为是可变的。我们总能做到以下,

Dimension d = new Dimension();
d.setSize(10, 20);// Dimension changed
d.setSize(10, 200);// Dimension changed
d.setSize(100, 200);// Dimension changed

让我们以不同的方式看到我们可以在Java中创建一个String。

String str1 = "Hey!";
String str2 = "Jack";
String str3 = new String("Hey Jack!");
String str4 = new String(new char[] {'H', 'e', 'y', '!'});
String str5 = str1 + str2;
str1 = "Hi !";
// ...

所以,

  1. str1str2是在String常量池中创建的字符串文字
  2. str3str4str5是放置在堆内存中的字符串对象
  3. str1 = "Hi!";在String常量池中创建"Hi!",它与"Hey!"之前引用的str1完全不同。

这里我们创建String文字或String对象。两者都不同,我建议你阅读以下帖子,了解更多相关信息。

在任何String声明中,有一件事是常见的,它不会修改但会被创建或转移到其他。

String str = "Good"; // Create the String literal in String pool
str = str + " Morning"; // Create String with concatenation of str + "Morning"
|_____________________|
       |- Step 1 : Concatenate "Good"  and " Morning" with StringBuilder
       |- Step 2 : assign reference of created "Good Morning" String Object to str

String如何变为不可变?

它是不变的行为,意味着,一旦分配的值不能以任何其他方式更新。 String类在内部保存字符数组中的数据。而且,类被创建为不可变的。看一下这个策略来定义不可变类。

移动参考并不意味着您改变了它的值。如果你可以更新String类中场景后面的字符数组,那将是可变的。但实际上,该阵列将被初始化一次,并且在整个程序中它仍然是相同的。

为什么StringBuffer是可变的?

正如您已经猜到的,StringBuffer类本身是可变的,因为您可以直接更新它的状态。与String类似,它也在字符数组中保存值,您可以通过不同的方法操作该数组,即追加,删除,插入等直接更改字符值数组。


1
投票

在Java中,所有字符串都是immutable(无法更改)。当您尝试修改String时,您真正在做的是创建一个新的。

按照我们可以创建字符串对象的方式

  1. 使用String文字 String str="java";
  2. 使用新关键字 String str = new String("java");
  3. 使用字符数组 char[] helloArray = { 'h', 'e', 'l', 'l', 'o', '.' }; String helloString = new String(helloArray);

字符串不变性只是意味着不可修改或不可更改

我们举一个例子

我正在初始化String文字的值

String s="kumar";

下面我将使用hashcode()显示位置地址的十进制表示

System.out.println(s.hashCode());

只需打印String的值即可

System.out.println("value "+s);

好的,这次我将值“kumar”初始化为s1

String s1="kumar";   // what you think is this line, takes new location in the memory ??? 

好的,我们通过显示我们创建的s1对象的哈希码来检查

System.out.println(s1.hashCode());

好的,让我们检查下面的代码

String s2=new String("Kumar");
    System.out.println(s2.hashCode());  // why this gives the different address ??

好的,最后检查下面的代码

String s3=new String("KUMAR");
    System.out.println(s3.hashCode());  // again different address ???

是的,如果你看到Strings的'和's1'具有相同的哈希码,因为's'和's1'保持的值与'kumar'相同

让我们考虑字符串's2'和's3'这两个字符串哈希码在某种意义上看起来是不同的,它们都存储在不同的位置,因为你看到它们的值是不同的。

因为s和s1哈希码是相同的,因为这些值是相同的并存储在相同的位置。

示例1:尝试以下代码并逐行分析

public class StringImmutable {
public static void main(String[] args) {

    String s="java";
    System.out.println(s.hashCode());
    String s1="javA";
    System.out.println(s1.hashCode());
    String s2=new String("Java");
    System.out.println(s2.hashCode());
    String s3=new String("JAVA");
    System.out.println(s3.hashCode());
}
}

示例2:尝试下面的代码并逐行分析

public class StringImmutable {
    public static void main(String[] args) {

        String s="java";
        s.concat(" programming");  // s can not be changed "immutablity"
        System.out.println("value of s "+s);
        System.out.println(" hashcode of s "+s.hashCode());

        String s1="java";
        String s2=s.concat(" programming");   // s1 can not be changed "immutablity" rather creates object s2
        System.out.println("value of s1 "+s1);
        System.out.println(" hashcode of s1 "+s1.hashCode());  

        System.out.println("value of s2 "+s2);
        System.out.println(" hashcode of s2 "+s2.hashCode());

    }
}

好的,让我们来看看mutable和immutable之间的区别。

可变(它改变)与不可变(它不能改变)

public class StringMutableANDimmutable {
    public static void main(String[] args) {


        // it demonstrates immutable concept
        String s="java";
        s.concat(" programming");  // s can not be changed (immutablity)
        System.out.println("value of s ==  "+s); 
        System.out.println(" hashcode of s == "+s.hashCode()+"\n\n");


        // it demonstrates mutable concept
        StringBuffer s1= new StringBuffer("java");
        s1.append(" programming");  // s can be changed (mutablity)
        System.out.println("value of s1 ==  "+s1); 
        System.out.println(" hashcode of s1 == "+s1.hashCode());


    }
}

还有什么问题吗?请写上......


0
投票

我用输出注释修改了威廉的代码,以便更好理解

   static void changeStr(String in) { 
      in = in+" changed";
      System.out.println("fun:"+in); //value changed 
    }
    static void changeStrBuf(StringBuffer in) {
      in.append(" changed");   //value changed
    }

    public static void main(String[] args) {
       StringBuffer sb = new StringBuffer("value");
       String str = "value";
       changeStrBuf(sb);
       changeStr(str);
       System.out.println("StringBuffer: "+sb); //value changed
       System.out.println("String: "+str);       // value 
    }

在上面的代码中,查看main()和changeStr()中str的值,即使你在changeStr()中更改str的值,它只影响到该函数,但在main函数中,值不会改变,但它不是StringBuffer的情况..

在StringBuffer中,更改的值会受到全局影响..

因此String是不可变的,StringBuffer是可变的......

在Simple中,无论你改变为String对象,只会影响到该函数。转到String Pool。但没有改变......


0
投票

可变变量是其值可能在适当位置变化的变量,而在不可变变量中,变量值不会发生。修改不可变变量将重建相同的变量。

© www.soinside.com 2019 - 2024. All rights reserved.