简体   繁体   English

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

[英]What is difference between mutable and immutable String in java

As per my knowledge, 据我所知,

a mutable string can be changed, and an immutable string cannot be changed. 可以更改可变字符串,并且不能更改不可变字符串。

Here I want to change the value of String like this, 在这里,我想像这样更改String的值,

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

and other way is, 和其他方式是,

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

In both the cases I am trying to alter the value of str . 在这两种情况下,我都试图改变str的价值。 Can anyone tell me, what is difference in both case and give me clear picture of mutable and immutable objects. 任何人都可以告诉我,这两种情况有什么不同,并给我清晰的可变和不可变对象的图片。

Case 1: 情况1:

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

In the above code you create 3 String Objects. 在上面的代码中,您将创建3个String对象。

  1. "Good" it goes into the String Pool . “好”它进入字符串池
  2. " Morning" it goes into the String Pool as well. “早上”它也会进入字符串池
  3. "Good Morning" created by concatenating "Good" and " Morning". 通过连接“好”和“早晨”创造的“早安”。 This guy goes on the Heap . 这家伙继续

Note: Strings are always immutable . 注意:字符串总是不可变的 There is no, such thing as a mutable String . 没有,像一个可变的字符串 str is just a reference which eventually points to "Good Morning". str只是一个参考 ,最终指向“早安”。 You are actually, not working on 1 object. 实际上,你不是在处理1对象。 you have 3 distinct String Objects. 你有3不同的String对象。


Case 2: 案例2:

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

StringBuffer contains an array of characters. StringBuffer包含一个字符数组。 It is not same as a String . 这是相同的String The above code adds characters to the existing array. 上面的代码将字符添加到现有数组中。 Effectively, StringBuffer is mutable, its String representation isn't. 实际上, StringBuffer是可变的,它的String表示不是。

What is difference between mutable and immutable String in java java中的可变和不可变String之间有什么区别

immutable exist, mutable don't. 不可变的存在,可变的不存在。

In Java, all strings are immutable. 在Java中,所有字符串都是不可变的。 When you are trying to modify a String , what you are really doing is creating a new one. 当您尝试修改String ,您真正在做的是创建一个新的。 However, when you use a StringBuilder , you are actually modifying the contents, instead of creating a new one. 但是,当您使用StringBuilder ,实际上是在修改内容,而不是创建新内容。

Java String s are immutable. Java String是不可变的。

In your first example, you are changing the reference to the String , thus assigning it the value of two other Strings combined: str + " Morning" . 在第一个示例中,您正在更改对String引用 ,从而为其分配两个其他Strings组合的值: str + " Morning"

On the contrary, a StringBuilder or StringBuffer can be modified through its methods. 相反,可以通过其方法修改StringBuilderStringBuffer

When you say str , you should be careful what you mean: 当你说str ,你应该小心你的意思:

  • do you mean the variable str ? 你的意思是变量 str吗?

  • or do you mean the object referenced by str ? 或者你的意思是str引用的对象

In your StringBuffer example you are not altering the value of str , and in your String example you are not altering the state of the String object. 在您的StringBuffer示例中,您不会更改str的值,并且在String示例中,您不会更改String对象的状态。

The most poignant way to experience the difference would be something like this: 体验差异的最痛苦的方式是这样的:

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);
}

String in Java is immutable . Java中的字符串不可变的 However what does it mean to be mutable in programming context is the first question. 然而,在编程上下文中可变的意思是第一个问题。 Consider following class, 考虑下课,

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;
    }
}

Now after creating the instance of Dimension we can always update it's attributes. 现在,在创建Dimension实例后,我们总是可以更新它的属性。 Note that if any of the attribute, in other sense state, can be updated for instance of the class then it is said to be mutable. 注意,如果在其他意义状态中的任何属性可以更新为该类的实例,那么它被认为是可变的。 We can always do following, 我们总能做到以下,

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

Let's see in different ways we can create a String in Java. 让我们以不同的方式看到我们可以在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 !";
// ...

So, 所以,

  1. str1 and str2 are String literals which gets created in String constant pool str1str2是在String常量池中创建的字符串文字
  2. str3 , str4 and str5 are String Objects which are placed in Heap memory str3str4str5是放置在堆内存中的字符串对象
  3. str1 = "Hi!"; creates "Hi!" 创造"Hi!" in String constant pool and it's totally different reference than "Hey!" 在String常量池中,它与"Hey!"完全不同"Hey!" which str1 referencing earlier. 哪个str1早先引用。

Here we are creating the String literal or String Object. 这里我们创建String文字或String对象。 Both are different, I would suggest you to read following post to understand more about it. 两者都不同,我建议你阅读以下帖子,了解更多相关信息。

In any String declaration, one thing is common, that it does not modify but it gets created or shifted to other. 在任何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

How String became immutable ? String如何变为不可变?

It's non changing behaviour, means, the value once assigned can not be updated in any other way. 它是不变的行为,意味着,一旦分配的值不能以任何其他方式更新。 String class internally holds data in character array. String类在内部保存字符数组中的数据。 Moreover, class is created to be immutable. 而且,类被创建为不可变的。 Take a look at this strategy for defining immutable class. 看一下这个策略来定义不可变类。

Shifting the reference does not mean you changed it's value. 移动参考并不意味着您改变了它的值。 It would be mutable if you can update the character array which is behind the scene in String class. 如果你可以更新String类中场景后面的字符数组,那将是可变的。 But in reality that array will be initialized once and throughout the program it remains the same. 但实际上,该阵列将被初始化一次,并且在整个程序中它仍然是相同的。

Why StringBuffer is mutable ? 为什么StringBuffer是可变的?

As you already guessed, StringBuffer class is mutable itself as you can update it's state directly. 正如您已经猜到的,StringBuffer类本身是可变的,因为您可以直接更新它的状态 Similar to String it also holds value in character array and you can manipulate that array by different methods ie append, delete, insert etc. which directly changes the character value array. 与String类似,它也在字符数组中保存值,您可以通过不同的方法操作该数组, 追加,删除,插入等直接更改字符值数组。

In Java, all strings are immutable (Can't change). 在Java中,所有字符串都是不可变的 (不能更改)。 When you are trying to modify a String, what you are really doing is creating a new one . 当您尝试修改String时,您真正在做的是创建一个新的

Following ways we can create the string object 按照我们可以创建字符串对象的方式

  1. Using String literal 使用String文字

     String str="java"; 
  2. Using new keyword 使用新关键字

     String str = new String("java"); 
  3. Using character array 使用字符数组

     char[] helloArray = { 'h', 'e', 'l', 'l', 'o', '.' }; String helloString = new String(helloArray); 

coming to String immutability, simply means unmodifiable or unchangeable 字符串不变性只是意味着不可修改或不可更改

Let's take one example 我们举一个例子

I'm initializing the value to the String literal s 我正在初始化String文字的值

String s="kumar";

Below I'm going to display the decimal representation of the location address using hashcode() 下面我将使用hashcode()显示位置地址的十进制表示

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

Simply printing the value of a String s 只需打印String的值即可

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

Okay, this time I'm inittializing value "kumar" to s1 好的,这次我将值“kumar”初始化为s1

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

Okay let's check by displaying hashcode of the s1 object which we created 好的,我们通过显示我们创建的s1对象的哈希码来检查

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

okay, let's check below code 好的,让我们检查下面的代码

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

Okay, check this below code at last 好的,最后检查下面的代码

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

YES, if you see Strings 's' and 's1' having the same hashcode because the value hold by 's' & 's1' are same that is 'kumar' 是的,如果你看到Strings的'和's1'具有相同的哈希码,因为's'和's1'保持的值与'kumar'相同

Let's consider String 's2' and 's3' these two Strings hashcode appears to be different in the sense, they both stored in a different location because you see their values are different. 让我们考虑字符串's2'和's3'这两个字符串哈希码在某种意义上看起来是不同的,它们都存储在不同的位置,因为你看到它们的值是不同的。

since s and s1 hashcode is same because those values are same and storing in the same location. 因为s和s1哈希码是相同的,因为这些值是相同的并存储在相同的位置。

Example 1: Try below code and analyze line by line 示例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());
}
}

Example 2: Try below code and analyze line by line 示例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());

    }
}

Okay, Let's look what is the difference between mutable and immutable. 好的,让我们来看看mutable和immutable之间的区别。

mutable(it change) vs. immutable (it can't change) 可变(它改变)与不可变(它不能改变)

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());


    }
}

Any further questions?? 还有什么问题吗? please write on... 请写上......

I modified the code of william with a output comments for better understandable 我用输出注释修改了威廉的代码,以便更好理解

   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 
    }

In above code , look at the value of str in both main() and changeStr() , even though ur changing the value of str in changeStr() it is affecting only to that function but in the main function the value is not changed , but it not in the case of StringBuffer.. 在上面的代码中,查看main()和changeStr()中str的值,即使你在changeStr()中更改str的值,它只影响该函数,但在main函数中,值不会改变,但它不是StringBuffer的情况..

In StringBuffer changed value is affected as a global.. 在StringBuffer中,更改的值会受到全局影响..

hence String is immutable and StringBuffer is mutable... 因此String是不可变的,StringBuffer是可变的......

In Simple , whatever u changed to String Object will affecting only to that function By going to String Pool. 在Simple中,无论你改变为String对象,只会影响到该函数。转到String Pool。 but not Changed... 但没有改变......

A mutable variable is one whose value may change in place, whereas in an immutable variable change of value will not happen in place. 可变变量是其值可能在适当位置变化的变量,而在不可变变量中,变量值不会发生。 Modifying an immutable variable will rebuild the same variable. 修改不可变变量将重建相同的变量。

Mutable means you will save the same reference to variable and change its contents but immutable you can not change contents but you will declare new reference contains the new and the old value of the variable Mutable意味着您将保存对变量的相同引用并更改其内容但不可变您不能更改内容但您将声明新引用包含变量的旧值和旧值

Ex Immutable -> String Ex Immutable - > String

String x = "value0ne";// adresse one x += "valueTwo"; //an other adresse {adresse two} String x = "value0ne";// adresse one x += "valueTwo"; //an other adresse {adresse two} adresse on the heap memory change. String x = "value0ne";// adresse one x += "valueTwo"; //an other adresse {adresse two}对堆内存更改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 Mutable - > StringBuffer - StringBuilder StringBuilder sb = new StringBuilder(); sb.append("valueOne"); // adresse One sb.append("valueTwo"); // adresse One StringBuilder sb = new StringBuilder(); sb.append("valueOne"); // adresse One sb.append("valueTwo"); // adresse One

sb still in the same adresse i hope this comment helps 我仍然在同一个地方,我希望这个评论有所帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM