字符串对象和字符串文字之间的区别

发布于 2024-09-10 22:15:23 字数 126 浏览 11 评论 0原文

有什么区别

String str = new String("abc");

String str = "abc";

What is the difference between

String str = new String("abc");

and

String str = "abc";

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

江挽川 2024-09-17 22:15:23

当您使用字符串文字时,字符串可以interned,但是当你使用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

一般来说,您应该尽可能使用字符串文字表示法。它更容易阅读,并且让编译器有机会优化您的代码。

When you use a string literal the string can be interned, but when you use new String("...") you get a new string object.

In this example both string literals refer the same object:

String a = "abc"; 
String b = "abc";
System.out.println(a == b);  // true

Here, 2 different objects are created and they have different references:

String c = new String("abc");
String d = new String("abc");
System.out.println(c == d);  // false

In general, you should use the string literal notation when possible. It is easier to read and it gives the compiler a chance to optimize your code.

笔落惊风雨 2024-09-17 22:15:23

字符串文字是一个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将不会创建一个new String 对象,但使用缓存 String 的引用。

s2 保证是一个新的 String 对象,因此在本例中我们有:

s1 == s2 // is false
s1 == s3 // is true
s1.equals(s2) // is true

A String literal is a Java language concept. This is a String literal:

"a String literal"

A String object is an individual instance of the java.lang.String class.

String s1 = "abcde";
String s2 = new String("abcde");
String s3 = "abcde";

All are valid, but have a slight difference. s1 will refer to an interned String object. This means, that the character sequence "abcde" will be stored at a central place, and whenever the same literal "abcde" is used again, the JVM will not create a new String object but use the reference of the cached String.

s2 is guranteed to be a new String object, so in this case we have:

s1 == s2 // is false
s1 == s3 // is true
s1.equals(s2) // is true
凉世弥音 2024-09-17 22:15:23

长答案可以在此处找到,所以我会给你一个简短的答案。

当您执行此操作时:

String str = "abc";

您正在调用 字符串。此方法引用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;

在本例中,strstr2 是对不同 的引用>Objects,两者都没有被interned,因此当您使用 == 测试 Object 身份时,您将得到

就良好的编码实践而言:不要使用 == 来检查字符串是否相等,而是使用 .equals()

The long answer is available here, so I'll give you the short one.

When you do this:

String str = "abc";

You are calling the intern() method on String. This method references an internal pool of String objects. If the String you called intern() on already resides in the pool, then a reference to that String is assigned to str. If not, then the new String is placed in the pool, and a reference to it is then assigned to str.

Given the following code:

String str = "abc";
String str2 = "abc";
boolean identity = str == str2;

When you check for object identity by doing == (you are literally asking: do these two references point to the same object?), you get true.

However, you don't need to intern() Strings. You can force the creation on a new Object on the Heap by doing this:

String str = new String("abc");
String str2 = new String("abc");
boolean identity = str == str2;

In this instance, str and str2 are references to different Objects, neither of which have been interned, so that when you test for Object identity using ==, you will get false.

In terms of good coding practice: do not use == to check for String equality, use .equals() instead.

落花浅忆 2024-09-17 22:15:23

由于字符串是不可变的,当您这样做时:

String a = "xyz"

在创建字符串时,JVM 在字符串池中搜索是否已存在字符串值 "xyz",如果存在 'a' 将只是该字符串的引用,并且不会创建新的 String 对象。

但如果您说:

String a = new String("xyz")

您强制 JVM 创建一个新的 String 引用,即使 "xyz" 在其池中。

有关更多信息,请阅读

As Strings are immutable, when you do:

String a = "xyz"

while creating the string, the JVM searches in the pool of strings if there already exists a string value "xyz", if so 'a' will simply be a reference of that string and no new String object is created.

But if you say:

String a = new String("xyz")

you force JVM to create a new String reference, even if "xyz" is in its pool.

For more information read this.

天涯离梦残月幽梦 2024-09-17 22:15:23

"abc" 是一个文字字符串。

在 Java 中,这些文字字符串在内部进行池化,并且在代码中声明该字符串文字的任何地方都会使用 "abc" 的相同 String 实例。因此 "abc" == "abc" 将始终为 true,因为它们都是相同的 String 实例。

使用 字符串.intern() 方法中,您可以将任何您喜欢的字符串添加到内部池字符串中,这些字符串将保留在内存中,直到 java 退出。

另一方面,使用 new String("abc") 将在内存中创建一个新的字符串对象,其逻辑上与 "abc" 文字相同。
"abc" == new String("abc") 始终为 false,因为尽管它们在逻辑上相等,但它们引用不同的实例。

将 String 构造函数包装在字符串文字周围没有任何价值,它只是不必要地使用了比需要更多的内存。

"abc" is a literal String.

In Java, these literal strings are pooled internally and the same String instance of "abc" is used where ever you have that string literal declared in your code. So "abc" == "abc" will always be true as they are both the same String instance.

Using the String.intern() method you can add any string you like to the internally pooled strings, these will be kept in memory until java exits.

On the other hand, using new String("abc") will create a new string object in memory, which is logically the same as the "abc" literal.
"abc" == new String("abc") will always be false, as although they are logically equal they refer to different instances.

Wrapping a String constructor around a string literal is of no value, it just needlessly uses more memory than it needs to.

花开浅夏 2024-09-17 22:15:23

String是Java中与其他编程语言不同的类。因此,对于每个类,对象声明和初始化都是

String st1 = new String();

or

String st2 = new String("Hello"); 
String st3 = new String("Hello");

这里,st1、st2 和 st3 是不同的对象。

即:

st1 == st2 // false
st1 == st3 // false
st2 == st3 // false

因为 st1st2st3 引用了 3 个不同的对象,并且 == 检查相等性在内存位置,因此结果。

但是:

st1.equals(st2) // false
st2.equals(st3) // true

这里 .equals() 方法检查内容,以及 st1 = ""st2 = "hello" 和 <代码>st3 =“你好”。于是就有了这样的结果。

在 String 声明的情况下

String st = "hello";

,调用 String 类的 intern() 方法,并检查 "hello" 是否在 intern 中如果没有,则添加到intern池中,如果intern池中存在“hello”,则st将指向已存在的“hello”的内存。

因此,如果是:

String st3 = "hello";
String st4 = "hello"; 

这里:

st3 == st4 // true

因为 st3st4 指向相同的内存地址。

还:

st3.equals(st4);  // true as usual

String is a class in Java different from other programming languages. So as for every class the object declaration and initialization is

String st1 = new String();

or

String st2 = new String("Hello"); 
String st3 = new String("Hello");

Here, st1, st2 and st3 are different objects.

That is:

st1 == st2 // false
st1 == st3 // false
st2 == st3 // false

Because st1, st2, st3 are referencing 3 different objects, and == checks for the equality in memory location, hence the result.

But:

st1.equals(st2) // false
st2.equals(st3) // true

Here .equals() method checks for the content, and the content of st1 = "", st2 = "hello" and st3 = "hello". Hence the result.

And in the case of the String declaration

String st = "hello";

Here, intern() method of String class is called, and checks if "hello" is in intern pool, and if not, it is added to intern pool, and if "hello" exist in intern pool, then st will point to the memory of the existing "hello".

So in case of:

String st3 = "hello";
String st4 = "hello"; 

Here:

st3 == st4 // true

Because st3 and st4 pointing to same memory address.

Also:

st3.equals(st4);  // true as usual
够钟 2024-09-17 22:15:23

在第一种情况下,创建了两个对象。

在第二种情况下,只有一个。

尽管这两种方式 str 都引用 "abc"

In the first case, there are two objects created.

In the second case, it's just one.

Although both ways str is referring to "abc".

但可醉心 2024-09-17 22:15:23

一些拆解总是很有趣......

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

Some disassembly is always interesting...

$ 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
}
娇柔作态 2024-09-17 22:15:23

除了已经发布的答案之外,还可以参见这篇关于javaranch的优秀文章。

In addition to the answers already posted, also see this excellent article on javaranch.

皓月长歌 2024-09-17 22:15:23

根据 String 类文档< /a> 它们是等价的。

String(String original) 的文档还指出:除非需要原始的显式副本,否则无需使用此构造函数,因为字符串是不可变的。

寻找其他响应,因为 Java 文档似乎具有误导性:(

According to String class documentation they are equivalent.

Documentation for String(String original) also says that: Unless an explicit copy of original is needed, use of this constructor is unnecessary since Strings are immutable.

Look for other responses, because it seems that Java documentation is misleading :(

空心空情空意 2024-09-17 22:15:23

以下是一些比较:

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() 时,引用会发生更改。

The following are some comparisons:

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

When intern() is called the reference is changed.

早乙女 2024-09-17 22:15:23

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”将
被放置在水池中。

There is a subtle differences between String object and string literal.

String s = "abc"; // creates one String object and one reference variable

In this simple case, "abc" will go in the pool and s will refer to it.

String s = new String("abc"); // creates two objects,and one reference variable

In this case, because we used the new keyword, Java will create a new String object
in normal (non-pool) memory, and s will refer to it. In addition, the literal "abc" will
be placed in the pool.

櫻之舞 2024-09-17 22:15:23

String s = new String("FFFF") 创建 2 个对象:"FFFF" 字符串和 String 对象,它们指向 " FFFF” 字符串,所以它就像指针到指针(引用到引用,我不热衷于术语)。

据说你永远不应该使用new String("FFFF")

String s = new String("FFFF") creates 2 objects: "FFFF" string and String object, which point to "FFFF" string, so it is like pointer to pointer (reference to reference, I am not keen with terminology).

It is said you should never use new String("FFFF")

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文