Javaにリテラルが存在する唯一のクラスがStringなのはなぜですか?
質問
java.lang.String
が2つの作成方法が存在する唯一のクラスである理由:
1)通常の方法で" new
"キーワード。
String s = new String("abc");
2) String
リテラル( String
クラスでのみ使用可能)
String s = "abc";
では、なぜ String
リテラルがあり、他のクラスにはリテラルがないのですか?
解決
文字列は、通常のクラスでありながら、プログラミングの基本要素の1つを表します(その他は数値とブール値です)。したがって、JavaはStringオブジェクトを初日から準プリミティブ変数と見なし、これを許可しました。
その後、自動ボクシングが標準コンパイラの一部になったときに、この方法で数値ラッパーオブジェクトを構築することもできます。つまり、
Integer i = 123;
Tom Hawtin-tacklineが質問へのコメントで言及しているように。
他のヒント
簡単な答え。言語設計者がそのように感じたからです。
文字列は、例外を作った一般的なクラスだと思います。他にも同様の例外がいくつかあるはずです(Tom Hawtinsのコメントを参照)
オートボクシング(IMOはカウントしません-リテラルはクラスではなくプリミティブ型のためのものです。ラッパークラスへの暗黙的な変換があります)、 String(String)
コンストラクタ実際に便利です。文字データのコピーを取得します。つまり、元の文字列が小さいが、バッキング char []
が大きい場合、新しい文字列はそれに依存しません。
これは、たとえばファイルから短い行を読み取る場合に重要になることがあります。
文字列リテラルが存在する理由については、それらが有用だからです。代わりに何がありますか?開発者に強制的に使用させますか:
String x = new String(new char[] { 'h', 'e', 'l', 'l', 'o' });
同時にインターンを取得しませんか?
他のどのクラスにリテラルを追加しますか?おそらく、マップとリストのリテラルは便利でしょう。Java7で提供されているかどうかは思い出せません。配列初期化子は「リテラルのようなビット」と考えることができます。オブジェクトの初期化の省略形であるという点で。
文字列は基本データ型のようなものであるため、プリミティブと同じレベルにあると見なされます。
ところで、
new String("abc");
実際には2つの文字列を作成します:
- インターンしたもののうち、参照を失ったもの
- 同じコンテンツを持つ新しいインスタンス
個人的には、Stringのコンストラクターを使用する必要性はありません。
リテラルを持つオブジェクトタイプはです。文字列、 null およびクラスリテラル。
配列<の初期化子を使用することもできますおよびプリミティブリテラルは、「2つの作成方法」に適合する初期化子として使用される場合、オブジェクトの作成にも使用できます。真のリテラルではない単純な構文(オブジェクト式が発生する可能性があるすべての場所ではなく、値の初期化にのみ使用できます)。
シリアル化やリフレクションなどの他の手法を使用する場合、「2つの作成方法」を破ることができます。
Java 7は、配列リテラルのようなリテラルを介して初期コレクションに機能を提供する予定です:
最後に確認した内容:
Integer wInt = 1;
正常に動作します。
作成の後者の形式には、文字列インターンも含まれます。つまり、コードがある場合:
String s = "abc";
String t = "abc";
コンパイラはこれを最適化し、同じStringオブジェクトへの2つの参照を取得します。 (s == tはtrueになります)。
文字列インターンは文字列式でも機能します。
もちろん、すべてのプリミティブ数値型のリテラル、trueとfalseのブール値、およびcharsもあります。あなたはあなたの質問で技術的に「他のクラスのリテラルはありません」と言ったと答えることができると思います。はい。誰かが「ヌル」と指摘したと思う。リテラルオブジェクトであるため、ステートメントは技術的に不正確ですが、それが他の唯一の例だと思います。
しかし、次の明白な質問は、他のどのクラスにリテラルを持たせたいですか?言語を設計している場合、BufferedReaderリテラルはどのようになりますか?または、ResultSetリテラルですか?またはJCheckBoxですか?
たとえば、「ファイルリテラル」というように、理論的に言うことができます。 &quot; $ / home / bob / myfile.txt $&quot;のような特別な区切り文字で囲まれたファイル名です。しかし、誰かが「JButtonについてはどうだろう」と言えば、ボタンのテキストと、それが起動するActionListenerおよび適切な区切り文字(&quot;%Submit、SubmitListener%&quot;など)のようなリテラルを作成できませんでした。次に、ソケットについてはどうでしょうか。ホスト名を特別な区切り文字などに入れることはできませんでした。区切り文字として使用する句読点がすぐになくなるのは明らかだと思います。そのため、File(&quot; /home/bob/myfile.txt")やSocket(&quot; www.example.com&quot;などと言って、話しているクラスを識別するために何らかのテキストを記述する必要があります。 、631)。しかし、それはコンストラクタに非常によく似ており、Javaの作成者が実際に行ったことにすぐに戻ります。
「モノ」の数値の性質だけで表現できる(たとえば、すべての数字が数字リテラルを作成する)か、句読点を使用すると、キーボードに合理的に収まる句読点の数によってかなり制限されます。そして、あなたが話したいかもしれないすべてのさまざまな種類の600個の特別なアイコンを備えたキーボードが欲しいですか?言葉はとても簡単で柔軟です。
文字列は非常に一般的に使用されており、代替は非常に厄介であるため、特殊なケースにすることは理にかなっています。
文字列リテラルは、優先度(C)と構文が確立された便利なショートカットです。 JavaデザイナーがC ++プログラマーを誘惑したい場合、文字列リテラルがそこになければなりませんでした。幸いなことに、文字列の処理はC ++よりもJavaの方がはるかに安全です。
他の標準オブジェクトには事実上の構文はありませんでした-マップリテラルをどのように記述しますか?