数分前にこの質問を見て、Java String クラスを調べて、+
演算子のオーバーロードが発生していないかどうかを確認することにしました。
何も見つかりませんでしたが、これができることはわかっています
String ab = "ab";
String cd = "cd";
String both = ab + cd; //both = "abcd"
それはどこに実装されていますか?
数分前にこの質問を見て、Java String クラスを調べて、+
演算子のオーバーロードが発生していないかどうかを確認することにしました。
何も見つかりませんでしたが、これができることはわかっています
String ab = "ab";
String cd = "cd";
String both = ab + cd; //both = "abcd"
それはどこに実装されていますか?
ファインマニュアルから:
Java 言語は、文字列連結演算子 ( + ) と、他のオブジェクトの文字列への変換を特別にサポートしています。
StringBuilder
文字列の連結は、 (orStringBuffer
) クラスとそのappend
メソッドによって実装されます。文字列変換は、Object によって定義され、Java のすべてのクラスによって継承されるメソッド toString によって実装されます。文字列の連結と変換の詳細については、Gosling、Joy、および Steele によるThe Java Language Specificationを参照してください。
JLS の文字列連結を参照してください。
コンパイラは、コードを次のように記述したかのように扱います。
String both = new StringBuilder().append(ab).append(cd).toString();
編集:参照はありますか?OPのコードをコンパイルおよび逆コンパイルすると、次のようになります。
0: ldc #2; //String ab
2: astore_1
3: ldc #3; //String cd
5: astore_2
6: new #4; //class java/lang/StringBuilder
9: dup
10: invokespecial #5; //Method java/lang/StringBuilder."<init>":()V
13: aload_1
14: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: aload_2
18: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
24: astore_3
25: return
というわけで、言った通りです。
ここでの答えのほとんどは正しいです(コンパイラによって処理され、 + は .append() に変換されます...)
誰もが String のソース コードを見て、ある時点で追加する必要があることを付け加えたいと思います。これは非常に印象的です。
私はそれが次のようなものになったと信じています:
"a"+"b"+"c"
=
new String().append("a").append("b").append("c")
しかし、その後、いくつかの魔法が起こります。これは次のようになります。
ほとんどの人はそれが「ab」を作成すると信じていますが、「abc」を作成すると破棄されます。チェーンされていることを実際に理解し、何らかの操作を行います。
文字列「abc」があり、「bc」であることが判明した部分文字列を要求した場合、それらはまったく同じ基本配列を共有できるというトリックもあります。開始位置、終了位置、および「共有」フラグがあることに気付くでしょう。
実際、共有されていない場合、文字列の長さを拡張して他の文字列をコピーすることができます。
今、私はただ混乱しています。ソースコードを読んでください。かなりクールです。
これはコンパイラによって処理されます。
これは、言語仕様に記載されている特別な動作です。
15.18.1 文字列連結演算子 +
1 つのオペランド式のみが String 型である場合は、もう一方のオペランドに対して文字列変換が実行され、実行時に文字列が生成されます。結果は、2 つのオペランド文字列の連結である String オブジェクト (式がコンパイル時の定数式 (§15.28) でない限り、新しく作成された) への参照です。新しく作成された文字列では、左側のオペランドの文字が右側のオペランドの文字よりも前になります。String 型のオペランドが null の場合、そのオペランドの代わりに文字列 "null" が使用されます。
String
コンパイラレベルでは、int、double、float などと同じように標準型として定義されています。基本的に、すべてのコンパイラには演算子のオーバーロードがあります。演算子のオーバーロードは、開発者向けには定義されていません (C++ とは異なります)。
興味深いことに、この質問はバグとして記録されました: http://bugs.sun.com/view_bug.do?bug_id=4905919
それは言語レベルで行われます。Java 言語仕様は、文字列の追加が何をしなければならないかについて非常に具体的です。