[解決済み] Stringクラスは、どのように+演算子をオーバーライドするのですか?
質問
JavaではStringはクラスなのに、なぜ+演算子でStringを足すことができるのですか? また
String.java
のコードでは、この演算子の実装は見つかりませんでした。このコンセプトはオブジェクト指向に違反しているのでしょうか?
どのように解決するのですか?
Javaで次のような簡単な式を見てみましょう。
int x=15;
String temp="x = "+x;
コンパイラは
"x = "+x;
を
StringBuilder
に変換し、内部で
.append(int)
を使用して、整数を文字列に追加しています。
文字列変換により、任意の型をString型に変換することができます。
プリミティブ型Tの値xは、まず参照値に変換されます。 適切なクラスインスタンス生成式の引数として与えることによって を生成する式(15.9節)の引数として与えることにより、あたかも参照値に変換されます。
- Tがbooleanの場合、new Boolean(x)を使用します。
- Tがcharの場合、new Character(x)を使用します。
- Tがbyte、short、intの場合、new Integer(x)を使用します。
- Tがlongの場合、new Long(x)を使用します。
- Tがfloatの場合、new Float(x)を使用します。
- Tがdoubleであれば、new Double(x)を使用します。
この参照値は、文字列変換によってString型に変換されます。 変換されます。
あとは参照値のみを考慮すればよい。
- 参照がNULLの場合、文字列 "null"(4つのASCII文字 n, u, l, l )に変換されます。
- それ以外の場合は、あたかも参照されたオブジェクトのtoStringメソッドを引数なしで呼び出したかのように変換が行われます。 toStringメソッドの呼び出しの結果がNULLであった場合は 文字列 "null"が代わりに使用されます。
toStringメソッドは、原始クラスであるObject (§4.3.2). 多くのクラスがこれをオーバーライドしており、特にBoolean、Character, Integer、Long、Float、Double、そしてStringです。
文字列変換コンテキストの詳細については、§5.4を参照してください。
文字列連結の最適化: 実装では、変換と連結を一度に行うことで、中間値の生成と破棄を避けることができます。 を1つのステップで行い、中間的な 文字列オブジェクトの作成と破棄を避けるためです。繰り返される文字列連結のパフォーマンスを向上させるために Javaコンパイラは、繰り返される文字列連結のパフォーマンスを向上させるために、StringBufferクラスまたは同様の技術を使用して を使用して、式の評価によって生成される中間 String オブジェクトの数を減らすことができます。 の数を減らすことができます。
プリミティブな型については、実装はまた プリミティブ型から文字列に直接変換することで、ラッパーオブジェクトの生成を最適化することもできます。 型から文字列に直接変換することで、ラッパーオブジェクトの生成を排除することもできます。
最適化されたバージョンでは、実際には最初にフルラップされたStringの変換は行いません。
これは、プリミティブの変換を行わないとはいえ、コンパイラによって使用される最適化バージョンの良い例で、コンパイラがバックグラウンドでStringBuilderに変更するのがわかります。
http://caprazzi.net/posts/java-bytecode-string-concatenation-and-stringbuilder/
このjavaのコードです。
public static void main(String[] args) {
String cip = "cip";
String ciop = "ciop";
String plus = cip + ciop;
String build = new StringBuilder(cip).append(ciop).toString();
}
2つの連結スタイルがどのように全く同じバイトコードになるかを見てみましょう。
L0
LINENUMBER 23 L0
LDC "cip"
ASTORE 1
L1
LINENUMBER 24 L1
LDC "ciop"
ASTORE 2
// cip + ciop
L2
LINENUMBER 25 L2
NEW java/lang/StringBuilder
DUP
ALOAD 1
INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;
INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
ASTORE 3
// new StringBuilder(cip).append(ciop).toString()
L3
LINENUMBER 26 L3
NEW java/lang/StringBuilder
DUP
ALOAD 1
INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
ASTORE 4
L4
LINENUMBER 27 L4
RETURN
上の例と、与えられた例のソースコードに基づくバイトコードがどのように生成されるかを見てみると、コンパイラが内部で次のような文を変換していることに気づくことができます。
cip+ciop;
に
new StringBuilder(cip).append(ciop).toString();
つまり、演算子
+
は事実上、文字列連結のための省略記法で、より冗長な
StringBuilder
イディオムです。
関連
-
エラー java.util.NoSuchElementException
-
javaでクラスを作成すると、enclosing classでないように見える
-
[解決済み] JavaScriptで文字列が部分文字列を含むかどうかを確認する方法は?
-
[解決済み] C#のStringとstringの違いは何ですか?
-
[解決済み] JavaでInputStreamを読み込んでStringに変換するにはどうすればよいですか?
-
[解決済み] Pythonには文字列の'contains'サブストリングメソッドがありますか?
-
[解決済み] バイトを文字列に変換する
-
[解決済み] JavaBeanとは何ですか?
-
[解決済み] Pythonのクラスはなぜオブジェクトを継承するのですか?
-
[解決済み】JavaScriptで文字列の出現箇所をすべて置換する方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
javaの実行中に「javaの例外が発生しました」と表示された場合はどうすればよいですか?
-
jd-gui Java Exceptionが発生しました。
-
final, finally, finalizeの違いについて話してください。
-
javaの模造品QQ WeChatのチャットルーム
-
プロジェクトの依存関係を解決できなかった 解決
-
自動配線された依存性のインジェクションに失敗しました。
-
linux run jarfile Invalid or corrupt jarfile error.
-
アイデア Springboot Web プロジェクトを jar にパッケージ化する場合、Error: 無効または破損した jarfile x.jar 解決策
-
起動時にEclipseエラーが発生しました。起動中に内部エラーが発生しました。java.lang.NullPoin: "Javaツーリングの初期化 "中に内部エラーが発生しました。
-
Google Chromeのエラー「Not allowed to load local resource」の解決策について