之间有什么区别
String str = new String("abc");
和
String str = "abc";
答案 0 :(得分:202)
当您使用字符串文字时,字符串可以是interned,但是当您使用new String("...")
时,您将获得一个新的字符串对象。
在此示例中,两个字符串文字都引用相同的对象:
String a = "abc";
String b = "abc";
System.out.println(a == b); // true
这里创建了两个不同的对象,它们具有不同的引用:
String c = new String("abc");
String d = new String("abc");
System.out.println(c == d); // false
通常,应尽可能使用字符串文字表示法。它更容易阅读,它为编译器提供了优化代码的机会。
答案 1 :(得分:85)
String literal 是一种Java语言概念。这是一个字符串文字:
"a String literal"
String对象是java.lang.String
类的单个实例。
String s1 = "abcde";
String s2 = new String("abcde");
String s3 = "abcde";
一切都有效,但略有不同。 s1
将引用 interned String对象。这意味着,字符序列"abcde"
将存储在中心位置,并且每当再次使用相同的文字"abcde"
时,JVM将不会创建新的String对象,而是使用< em> cached String。
s2
保证是新的String对象,所以在这种情况下我们有:
s1 == s2 // is false
s1 == s3 // is true
s1.equals(s2) // is true
答案 2 :(得分:40)
答案很长here,所以我会给你一个简短的答案。
执行此操作时:
String str = "abc";
您正在String上调用intern()
方法。此方法引用String
个对象的内部池。如果您调用的intern()
上的字符串已驻留在池中,则会将String
的引用分配给str
。如果没有,则新的String
将被放置在池中,然后将对它的引用分配给str
。
给出以下代码:
String str = "abc";
String str2 = "abc";
boolean identity = str == str2;
当您通过==
检查对象标识时(您实际上是在询问:这两个引用是否指向同一个对象?),您得到true
。
但是,您需要到intern()
Strings
。您可以通过执行以下操作强制在堆上的新Object
上创建:
String str = new String("abc");
String str2 = new String("abc");
boolean identity = str == str2;
在这种情况下,str
和str2
是对不同Objects
的引用,其中没有 interned ,因此当您测试{{ 1}}使用Object
进行身份识别,您将获得==
。
在良好的编码实践方面:不使用false
来检查字符串是否相等,而是使用==
。
答案 3 :(得分:35)
由于字符串是不可变的,所以:
String a = "xyz"
在创建字符串时,如果已存在字符串值"xyz"
,则JVM在字符串池中搜索,如果是,'a'
将只是该字符串的引用,并且没有新的String对象是创建
但如果你说:
String a = new String("xyz")
即使String
位于其池中,您也会强制JVM创建新的"xyz"
引用。
有关详细信息,请参阅this。
答案 4 :(得分:17)
"abc"
是一个文字字符串。
在Java中,这些文字字符串在内部汇集,并且在代码中声明了字符串文字的地方使用"abc"
的相同String实例。所以"abc" == "abc"
将永远为真,因为它们都是相同的String实例。
使用String.intern()
方法,您可以将任何您喜欢的字符串添加到内部池化的字符串中,这些字符串将保留在内存中,直到java退出。
另一方面,使用new String("abc")
将在内存中创建一个新的字符串对象,这在逻辑上与"abc"
文字相同。
"abc" == new String("abc")
将始终为false,因为尽管它们在逻辑上相等,但它们指的是不同的实例。
围绕字符串文字包装String构造函数是没有价值的,它只是不必要地使用了比它需要的更多的内存。
答案 5 :(得分:7)
String是Java中与其他编程语言不同的类。因此对于每个类,对象声明和初始化都是
String st1 = new String();
或
String st2 = new String("Hello");
String st3 = new String("Hello");
此处,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"
的内容。因此结果。
在String声明的情况下
String st = "hello";
此处调用intern()
类的String
方法,并检查"hello"
是否在实习池中,如果不是,则将其添加到实习池中,如果是“hello”存在于实习池中,然后st
将指向现有"hello"
的内存。
以下是:
String st3 = "hello";
String st4 = "hello";
下面:
st3 == st4 // true
因为st3
和st4
指向相同的内存地址。
此外:
st3.equals(st4); // true as usual
答案 6 :(得分:6)
在第一种情况下,创建了两个对象。
在第二种情况下,它只是一种。
虽然str
两种方式都指的是"abc"
。
答案 7 :(得分:5)
有些反汇编总是很有意思......
$ 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
}
答案 8 :(得分:5)
除了已发布的答案外,另请参阅this关于javaranch的优秀文章。
答案 9 :(得分:3)
根据String class documentation,它们是等效的。
String(String original)
的文档也说:除非需要明确的原始副本,否则不必使用此构造函数,因为字符串是不可变的。
寻找其他响应,因为Java文档似乎具有误导性:(
答案 10 :(得分:2)
以下是一些比较:
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()
时,引用会更改。
答案 11 :(得分:1)
String对象和字符串文字之间存在细微差别。
String s = "abc"; // creates one String object and one reference variable
在这个简单的情况下,“ abc ”将进入池中, s 将引用它。
String s = new String("abc"); // creates two objects,and one reference variable
在这种情况下,因为我们使用了new
关键字,Java将创建一个新的String对象
在普通(非池)内存中, s 将引用它。另外,文字“ abc ”会
放在游泳池里。
答案 12 :(得分:0)
String s = new String("FFFF")
创建了2个对象:"FFFF"
字符串和String
对象,它指向"FFFF"
字符串,所以它就像指向指针(引用参考,我是不热衷于术语。)
据说你不应该使用new String("FFFF")