据我所知,可变字符串可以被改变,而不可变字符串则不能。
在这里,我想像这样改变字符串的值,
String str="Good";
str=str+" Morning";
另一种方法是,
StringBuffer str= new StringBuffer("Good");
str.append(" Morning");
在这两种情况下,我都试图改变str
的值。有人能告诉我,在这两种情况下有什么区别,并给我解释可变和不可变对象的清晰图像吗?据我所知,可变字符串可以被改变,而不可变字符串则不能。
在这里,我想像这样改变字符串的值,
String str="Good";
str=str+" Morning";
另一种方法是,
StringBuffer str= new StringBuffer("Good");
str.append(" Morning");
在这两种情况下,我都试图改变str
的值。有人能告诉我,在这两种情况下有什么区别,并给我解释可变和不可变对象的清晰图像吗?String str = "Good";
str = str + " Morning";
在上面的代码中,你创建了3个String
对象。
注意:String
永远是不可变的。没有可变的String这样的东西。 str
只是一个指向"Good Morning"的引用。实际上,你并不是在处理1
个对象。你有3
个不同的String
对象。
StringBuffer str = new StringBuffer("Good");
str.append(" Morning");
StringBuffer
包含字符数组。它与 String
不同,不是 同一种类型。
上述代码将字符添加到现有数组中。实际上,StringBuffer
是可变的,但它的 String
表示形式不是。
str.append(" Morining")
," Morning" 存储在字符串池中吗? - perfectusStringBuffer
扮演了可变字符串的角色。请注意String
和仅仅的“string”之间的区别。 - William F. JamesonStringBuffer
并不扮演可变字符串的角色。它是一个可以转换为字符串的数组。一旦您在其上调用toString()
,然后添加字符并再次调用toString()
,您将拥有2个不同的字符串对象。 - TheLostMindString
。前者是一个通用概念,后者是 Java 类。在 Java 中,StringBuffer
绝对可以用作可变字符串的目的。 - William F. JamesonString
时,实际上是创建一个新的字符串。但是,当你使用StringBuilder
时,你实际上是修改了内容,而不是创建一个新的字符串。Java中的String
是不可变的。
在您的第一个示例中,您正在更改对String
的引用,从而将其赋值为两个其他Strings
组合而成的值:str +“ Morning”
。
相反,StringBuilder
或StringBuffer
可以通过其方法进行修改。
在 Java 中,String 是不可变的。然而,在编程上下文中,“可变”是什么意思呢?请考虑以下类:
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 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 !";
// ...
str1
和str2
是字符串字面量,在字符串常量池中创建。str3
,str4
和str5
是放置在堆内存中的字符串对象。str1 = "Hi!";
在字符串常量池中创建了"Hi!"
,与str1
之前引用的"Hey!"
完全不同。在这里,我们创建了字符串字面量或字符串对象。它们是不同的,我建议您阅读以下文章以了解更多信息。
在任何字符串声明中,有一件事是共同的,它不会被修改,但却被创建或转移到其他位置。
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类中背后的字符数组,则该类将是可变的。但实际上,数组将被初始化一次,并在整个程序中保持不变。
为什么StringBuffer是可变的?
正如您已经猜到的,StringBuffer类本身是可变的,因为您可以直接更新其状态。与String类类似,它也将值保存在字符数组中,并且您可以通过不同方法(例如append,delete,insert等)操纵该数组,从而直接更改字符值数组。
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);
}
Using String literal
String str="java";
Using new keyword
String str = new String("java");
Using character array
char[] helloArray = { 'h', 'e', 'l', 'l', 'o', '.' };
String helloString = new String(helloArray);
String s="kumar";
System.out.println(s.hashCode());
System.out.println("value "+s);
String s1="kumar"; // what you think is this line, takes new location in the memory ???
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 ???
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());
}
}
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());
}
}
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());
}
}
hashCode()
并不是“显示位置地址的十进制表示”,它只是基于字符串内容的计算,完全不适合确定两个实例是否相同("Aa".hashCode() == "BB".hashCode() == 2112
,但"Aa"
永远不会与"BB"
处于相同的位置)。 - undefined我修改了William的代码,并添加了输出注释以便更好地理解
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
}
StringBuffer
对象不是可变字符串。一旦创建了一个字符串,它就永远是不可变的。 - TheLostMindStringBuffer
是可变的字符串,而是在说StringBuffer
是可变的对象。现在我是正确的吗? - Raghu