252

違いは何ですか

String str = new String("abc");

String str = "abc";
4

13 に答える 13

216

文字列リテラルを使用すると、文字列をインターンできますが、使用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

一般に、可能であれば文字列リテラル表記を使用する必要があります。読みやすく、コンパイラがコードを最適化する機会を与えます。

于 2010-07-21T09:30:38.923 に答える
87

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
于 2010-07-21T09:42:10.727 に答える
42

長い答えはここにありますので、短い答えをあげましょう。

これを行うとき:

String str = "abc";

Stringintern()でメソッドを呼び出しています。このメソッドは、オブジェクトの内部プールを参照します。呼び出した文字列がすでにプールに存在する場合、その文字列への参照がに割り当てられます。そうでない場合は、新しいものがプールに配置され、それへの参照がに割り当てられます。Stringintern()StringstrStringstr

次のコードが与えられます:

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

==(文字通り質問している:これらの2つの参照は同じオブジェクトを指しているのか?)を実行してオブジェクトのIDを確認すると、が得られtrueます。

ただし、する必要はありませんintern() StringsObjectこれを行うことで、ヒープ上の新しいものに作成を強制できます。

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

この例では、strstr2は異なるへの参照Objectsであり、どちらもインターンされObjectていないため、を使用してIDをテストする==と、が取得されますfalse

優れたコーディング手法の観点から、文字列の同等性をチェックするためにを使用せ、代わりにを使用してください。==.equals()

于 2010-07-21T11:08:16.473 に答える
40

文字列は不変であるため、次のようにします。

String a = "xyz"

文字列の作成中に、JVM は文字列値が既に存在するかどうかを文字列のプールで検索します。存在する"xyz"場合'a'は単にその文字列の参照となり、新しい String オブジェクトは作成されません。

しかし、あなたが言うなら:

String a = new String("xyz")

Stringプール内にある場合でも、JVM に新しい参照を強制的に作成"xyz"させます。

詳細については、こちらをお読みください

于 2010-07-21T12:33:44.980 に答える
17

"abc"リテラル文字列です。

Java では、これらのリテラル文字列は内部的にプール"abc"され、コード内でその文字列リテラルが宣言されている場合は常に、同じ String インスタンスが使用されます。どちら"abc" == "abc"も同じ String インスタンスであるため、常に true になります。

String.intern()内部でプールされた文字列に任意の文字列を追加できるメソッドを使用すると、これらは Java が終了するまでメモリに保持されます。

一方、 usingはメモリ内に新しい文字列オブジェクトを作成します。これは論理的にリテラル new String("abc")と同じです。これらは論理的には同じですが、異なるインスタンスを参照しているため、常に false になります。"abc""abc" == new String("abc")

文字列リテラルを文字列コンストラクタでラップしても意味がありません。必要以上のメモリを不必要に使用するだけです。

于 2010-07-21T09:33:50.447 に答える
6

最初のケースでは、2 つのオブジェクトが作成されます。

2 番目のケースでは、1 つだけです。

どちらの方法strも参照していますが"abc"

于 2010-07-21T09:30:47.817 に答える
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
}
于 2010-07-21T10:00:34.477 に答える
5

すでに投稿されている回答に加えて、javaranch に関するこの優れた記事も参照してください。

于 2010-07-21T12:55:22.980 に答える
3

String クラスのドキュメントによると、それらは同等です。

のドキュメントにString(String original)も次のように書かれています。元の明示的なコピーが必要でない限り、文字列は不変であるため、このコンストラクターの使用は不要です。

Javaのドキュメントは誤解を招くように見えるので、他の回答を探してください:(

于 2010-07-21T09:32:59.580 に答える
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()呼び出されると、参照が変更されます。

于 2013-08-28T12:11:02.343 に答える
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 " がプールに配置されます。

于 2010-07-22T05:32:08.033 に答える
0

String s = new String("FFFF")"FFFF"文字列と文字列Stringを指すオブジェクトの2つのオブジェクトを作成する"FFFF"ため、ポインターからポインターへのようなものです(参照への参照、用語には熱心ではありません)。

絶対に使ってはいけないと言われていますnew String("FFFF")

于 2010-07-21T10:51:46.857 に答える