「」を使用して文字列を初期化するにはどうすればよいですか?


154

Stringが他のようにクラスである場合、二重引用符を使用してどのように初期化できますか?


25
文字列はVIPクラスです。" "はすでに文字列です!
johnchen902 2013

2
特別な意味はありません。私は非常に重要なことを意味しました。つまりjava.lang.String、Java言語を特別に扱います。
johnchen902 2013

16
その文字列は「他のクラスと同じ」だと誰が言ったのですか。他とは異なり、非常に特別なクラスです。あなたの仮定が間違っているので、質問は実際には答えられません。
Eric Lippert 2013

5
仮定が間違っているからといって、質問に答えられないという意味ではありません。正解はすでに197票です。
Koray Tugay 14

回答:


293

Java文字列は特別です

Javaの設計者は、言語のパフォーマンスを向上させるために、すべてをオブジェクトにするのではなく、オブジェクト指向言語でプリミティブ型を保持することにしました。プリミティブはコールスタックに格納され、必要なストレージスペースが少なく、操作が安価です。一方、オブジェクトはプログラムヒープに格納され、複雑なメモリ管理とより多くのストレージスペースが必要になります。

パフォーマンス上の理由から、Javaの文字列はプリミティブとクラスの間にあるように設計されています。

例えば

String s1 = "Hello";              // String literal
String s2 = "Hello";              // String literal
String s3 = s1;                   // same reference
String s4 = new String("Hello");  // String object
String s5 = new String("Hello");  // String object

ここに画像の説明を入力してください

注: 文字列リテラルは共通のプールに格納されます。これにより、同じ内容の文字列のストレージを共有してストレージを節約できます。Stringnew演算子を介して割り当てられたオブジェクトはに格納されheap、同じコンテンツのストレージは共有されません。


72
「共通プール」は通常、ヒープの一部であることに注意してください。
Joachim Sauer

3
@JoachimSauerはい..少しの利点があります:)それをメモに追加しました。覚えてくれてありがとう
Suresh Atta

2
文字列s1 = "Hello"を書く方が速いですか?文字列よりs2 = new String( "Hello");?
user2097804 2013

28
私はあなたの例にそれを追加しますs1 == s2 == s3しかしs4!= s5
Alfredo Osorio

8
@AndrewJanke最近のホットスポットjvm(7)では、文字列プールはperm genになく、Java 8以降はperm genはもうありません...
assylias 2013

50

JavaはStringを特別なクラスとして扱い、両方の方法で初期化できます

  1. リテラルを直接割り当てる

    String a = "adsasdf";
  2. 新しいキーワードを使用する他のオブジェクトとして

    String a = new String("adsasdf");

==記号と比較する場合は、特別な注意が必要です。

String a = "asdf";
String b = "asdf";
System.out.println(a == b);  // True
System.out.println(a.equals(b)); // True

String a = new String("asdf");
String b = new String("asdf");
System.out.println(a == b);  // False
System.out.println(a.equals(b)); // True

これは、最初のケースでは、オブジェクトaとbは呼び出されたものに保持されliteral pool、両方が同じオブジェクトを参照しているため、両方の点で等しいためです。

ただし、2番目のケースでは、他のオブジェクトを初期化するときのように、aとbは異なるオブジェクトを参照します。そのため、==演算子と比較した場合、値は等しくなりますが、等しくありません。


18

文字列はJLSで特別な扱いを受けます。これは、リテラルが存在する2つの非プリミティブ型の1つです(もう1つはClass*です。

JLSから:

文字列リテラルは、 `String [...]クラスのインスタンスへの参照です。

*まあ、「nullリテラル」の「null型」ありますnullが、ほとんどの人は「null型」を適切な型と考えていません。


1
「null型」がJavaの適切な型であることも知りませんでした。非常に役立つ情報です。フォントサイズを大きくする必要があります。
Grijesh Chauhan 2013

1
@GrijeshChauhan:まあ、「null型」はnull、任意の参照型変数に任意のものを割り当てることができるようにするための気の利いた表現です。それ以外の場合、これは興味深いタイプではありません。
Joachim Sauer

15

これはJava言語の機能です。ソースコード内の文字列リテラルは特別な扱いを受けます。

言語仕様は、ここでは、文字列リテラルはString型であると単に言っています


5

二重引用符で囲まれたテキストは、リテラルStringオブジェクトを作成します。

String myString = "Some text";

上記のコードは、String二重引用符を使用してオブジェクトを作成します。


4

文字列は、プログラミング言語でよく使用されます。javaはオブジェクト指向であるため、文字列はオブジェクトです。面倒な新しいString( "someString");を回避するには、文字列オブジェクトが必要になるたびに、javaでは、文字列リテラルを使用して文字列オブジェクトを作成できます。

ただし、文字列の等価性に留意する必要があります。ここに私が何を意味するかを示すための短いJUnitテストがあります。

    @Test
    public void stringTest() {
       // a string literal and a string object created 
       // with the same literal are equal
       assertEquals("string", new String("string"));

       // two string literals are the same string object
       assertSame("string", "string"); 

       // a string literal is not the same object instance 
       // as a string object created with the same string literal
       assertFalse("string" == new String("string"));

       // java's String.intern() method gives you the same
       // string object reference for all strings that are equal.
       assertSame("string", new String("string").intern());
    }

文字列をnew String(String src)でしか初期化できない場合、コンストラクタに文字列リテラルを与えることさえできません。を初期化してからchar []String(char [] src)コンストラクタを使用して文字列を作成するか、ファイルから文字列を読み取る必要があります。
AJMansfield 2013

不正解です。文字列リテラルは、二重引用符で囲まれたソースファイル内の文字シーケンスのみです。Javaは、このリテラルを使用して文字列のインスタンスを自動的に作成します。したがって、リテラルとStringオブジェクトは同じですが、同じではありません。Javaもこの方法で実装でき、new String( "");を使用する必要があります。Stringオブジェクトをインスタンス化しますが、これは私たちの生活をより困難にするだけです。したがって、新しいString( "a string")を記述すると、Javaはリテラル "a string"のStringオブジェクトを作成し、この文字列オブジェクトをnew Stringのコンストラクターに渡します。
ルネ・リンク

2

言及するだけです。文字列リテラルは、次のようなコードを記述できるStringクラスのインスタンスへの参照です。

 "abc" .getBytes();

 "a:b:c" .split( ":");

 "愛" .codePointAt(0);

2

-文字列内のクラスですジャワ。あなたはそれについて正しいので、いつでもnewキーワードで初期化できます。

-しかし、次のような場合:

String s = "";

上記のステートメントがでマークされているコンパイラであることを特別なStringオブジェクトとその後、ロード中にJVM(ロードが初期化前に行われる)クラスの、として知られているもの、これを見て、文字列リテラルに格納され、文字列リテラルプール

-したがって、文字列new()""メソッドを使用して作成できますが、後者は文字列リテラルプールからの参照があるため、文字列オブジェクトへの参照がない場合でもヒープに留まる文字列リテラルを提供します。


2

Javaは2つのステップからなるプロセスを実行します。

String str = "hello";

に相当

char data[] = {'h', 'e', 'l' , 'l', 'o'};
String str = new String(data);

[.NET] [1]も同様です。

String(Char[]) constructor

する

String(char[] value)

参照の追加:-


2
あなたが記述プロセスは、Javaが実際に何をするかではありません。他の人がすでに述べたように、"hello"文字列リテラルであると見、コンパイラによって定数プールに入れられますJLS 3.10.5JVMS§5.1を
siegi 2013

1

Java.lang.String単なるクラスではありません。これはコア言語の不可欠な部分です。コンパイラーはそのための構文糖を持っています。たとえば""、はの略語のようなものですnew String("")。書き込まれると""、コンパイラーは同一のストリングを同じインスタンスに最適化して、スペースを節約します。"a" + 5 == "a5" ==> true

コンパイラーには、オブジェクトバージョンとそのネイティブタイプの間でボックス化/ボックス化解除する必要がないこと、親がオブジェクトを意味しないこと、デフォルトのコンストラクターなど、多くのもののための構文シュガーがあります...


5
""はの省略形ではありませんnew String("")。を使用する""場合、最初に行われるのは、JVMの文字列プールで一致するものを探すことです。これがtrueの場合、その文字列を返します。を使用new String("")すると、文字列自体がすでに文字列プールに存在する場合でも、常に新しい文字列が作成されます(文字列プールに格納されないため)。
g00glen00b 2013

回答を更新しました。Lispシンボルタイプと同等の文字列定数を使用するなど、これを有利に使用しますか?
Sylwester 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.