两者有什么区别
String str = new String("abc");
而且
String str = "abc";
当你使用字符串字面值时,字符串可以是< / em > < em >拘留,但当你使用new String("...")时,你会得到一个新的字符串对象。
new String("...")
在这个例子中,两个字符串字面值引用同一个对象:
String a = "abc"; String b = "abc"; System.out.println(a == b); // true
这里创建了2个不同的对象,它们有不同的引用:
String c = new String("abc"); String d = new String("abc"); System.out.println(c == d); // false
一般来说,应该尽可能使用字符串文字表示法。它更容易阅读,并给编译器优化你的代码的机会。
在第一种情况下,创建了两个对象。
在第二种情况下,它只是一个。
尽管这两种方式str都指向"abc"。
str
"abc"
根据字符串类文档,它们是等价的。
String(String original)的文档也说:除非需要original的显式副本,否则使用此构造函数是不必要的,因为string是不可变的。
String(String original)
寻找其他的回答,因为Java文档似乎是误导性的:(
"abc"是一个字符串字面值。
在Java中,这些字面值字符串是内部池,并且在代码中声明该字符串字面值时使用"abc"的相同String实例。因此"abc" == "abc"将始终为真,因为它们都是相同的String实例。
"abc" == "abc"
使用String.intern()方法,你可以将你喜欢的任何字符串添加到内部池字符串中,这些字符串将一直保存在内存中,直到java退出。
String.intern()
new String("abc")
"abc" == new String("abc")
将String构造函数包装在字符串文字周围是没有价值的,它只是不必要地使用比它需要的更多内存。
字符串文字是一个Java语言概念。这是一个String字面值:
"a String literal"
字符串对象是java.lang.String类的一个单独实例。
java.lang.String
String s1 = "abcde"; String s2 = new String("abcde"); String s3 = "abcde";
都是有效的,但有细微的区别。s1将引用一个实习过 String对象。这意味着,字符序列"abcde"将被存储在一个中心位置,每当再次使用相同的字面"abcde"时,JVM将不会创建一个新的String对象,而是使用缓存 String的引用。
s1
"abcde"
s2肯定是new String对象,所以在这种情况下,我们有:
s2
s1 == s2 // is false s1 == s3 // is true s1.equals(s2) // is true
一些拆卸总是很有趣的……
$ cat Test.java public class Test { public static void main(String... args) { String abc = "abc"; String def = new String("def"); } } $ javap -c -v Test Compiled from "Test.java" public class Test extends java.lang.Object SourceFile: "Test.java" minor version: 0 major version: 50 Constant pool: const #1 = Method #7.#16; // java/lang/Object."<init>":()V const #2 = String #17; // abc const #3 = class #18; // java/lang/String const #4 = String #19; // def const #5 = Method #3.#20; // java/lang/String."<init>":(Ljava/lang/String;)V const #6 = class #21; // Test const #7 = class #22; // java/lang/Object const #8 = Asciz <init>; ... { public Test(); ... public static void main(java.lang.String[]); Code: Stack=3, Locals=3, Args_size=1 0: ldc #2; // Load string constant "abc" 2: astore_1 // Store top of stack onto local variable 1 3: new #3; // class java/lang/String 6: dup // duplicate top of stack 7: ldc #4; // Load string constant "def" 9: invokespecial #5; // Invoke constructor 12: astore_2 // Store top of stack onto local variable 2 13: return }
String s = new String("FFFF")创建了2个对象:"FFFF"字符串和String对象,它们指向"FFFF"字符串,所以它就像指针到指针(引用到引用,我不喜欢术语)。
String s = new String("FFFF")
"FFFF"
String
据说你永远不应该使用new String("FFFF")
new String("FFFF")
长答案是可用的在这里,所以我给你一个简短的。
当你这样做的时候:
你正在调用字符串上的intern()方法。String对象的引用内部池方法。如果你调用intern()的字符串已经存在于池中,那么对该String的引用将被赋值给str。如果不是,则将新的String放在池中,然后将对它的引用赋给str。
intern()
给定以下代码:
String str = "abc"; String str2 = "abc"; boolean identity = str == str2;
当你通过执行==来检查对象身份时(你实际上是在问:这两个引用是否指向同一个对象?),你会得到true。
==
true
但是,你不能将abc3转换为intern() Strings。你可以通过这样做强制在堆上的一个新的Object上创建:
Strings
Object
String str = new String("abc"); String str2 = new String("abc"); boolean identity = str == str2;
在这个例子中,str和str2是对不同Objects的引用,它们都不是实习过,所以当你使用==测试Object身份时,你会得到false。
str2
Objects
false
在良好的编码实践方面:如果不使用==来检查String是否相等,则使用.equals()来代替。
.equals()
由于字符串是不可变的,当你这样做时:
String a = "xyz"
在创建字符串时,JVM在字符串池中搜索是否已经存在字符串值"xyz",如果存在,'a'将只是该字符串的引用,并且不会创建新的string对象。
"xyz"
'a'
但如果你说:
String a = new String("xyz")
你强迫JVM创建一个新的String引用,即使"xyz"在它的池中。
更多信息请阅读这。
除了已经发布的答案,还可以查看这关于javaranche的优秀文章。
字符串对象和字符串文字之间有细微的区别。
String s = "abc"; // creates one String object and one reference variable
在这个简单的例子中,"美国广播公司"将进入池,年代将引用它。
String s = new String("abc"); // creates two objects,and one reference variable
new
以下是一些比较:
String s1 = "Hello"; String s2 = "Hello"; String s3 = new String("Hello"); System.out.println(s1 == s2); //true System.out.println(s1.equals(s2)); //true System.out.println(s1 == s3); //false System.out.println(s1.equals(s3)); //true s3 = s3.intern(); System.out.println(s1 == s3); //true System.out.println(s1.equals(s3)); //true
当intern()被调用时,引用被改变。
String是Java中不同于其他编程语言的一个类。因此,对于每个类,对象的声明和初始化是
String st1 = new String();
或
String st2 = new String("Hello"); String st3 = new String("Hello");
这里,st1, st2和st3是不同的对象。
st1
st2
st3
那就是:
st1 == st2 // false st1 == st3 // false st2 == st3 // false
因为st1, st2, st3引用了3个不同的对象,而==检查内存位置是否相等,因此结果为。
但是:
st1.equals(st2) // false st2.equals(st3) // true
这里.equals()方法检查内容,以及st1 = "", st2 = "hello"和st3 = "hello"的内容。这就是结果。
st1 = ""
st2 = "hello"
st3 = "hello"
在String声明的情况下
String st = "hello";
这里调用String类的intern()方法,并检查"hello"是否在实习生池中,如果不在,则将其添加到实习生池中,如果“hello”存在于实习生池中,则st将指向现有"hello"的内存。
"hello"
st
所以在这种情况下:
String st3 = "hello"; String st4 = "hello";
在这里:
st3 == st4 // true
因为st3和st4指向相同的内存地址。
st4
另外:
st3.equals(st4); // true as usual