Iteger+String など、JAVA によって提供される「+」演算子は、C++ の観点から見ると、JAVA がこの「+」演算子をどのようにオーバーロードするのかを常に知りたいと思っていたので、String クラスに調べに行きましたが、手がかりがないので、JAVA がどのように実装しているのか気になります。JAVA が「+ 演算子のオーバーロード」をどのように実装するかを段階的に分析してみましょう。
例
public class Example { public static void main(String[] args) { Integer a = null; String b = a + "456"; System.out.println(b); } }
このプログラムはとてもシンプルで、整数と文字列の「+」演算式です。実行結果: null456
サンプルプログラムを逆コンパイルします
コマンド:
javap -c Example
逆コンパイル結果は次のとおりです:
Compiled from "Example.java" public class com.boyu.budmw.test.Example extends java.lang.Object{ public com.boyu.budmw.test.Example(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: aconst_null 1: astore_1 2: new #2; //class java/lang/StringBuilder 5: dup 6: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V 9: aload_1 10: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; 13: ldc #5; //String 456 15: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 18: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 21: astore_2 22: getstatic #8; //Field java/lang/System.out:Ljava/io/PrintStream; 25: aload_2 26: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 29: return }
main関数部分を分析しましょう:
0: 定数nullをオペランドスタックにプッシュします
1 :オペランド スタックから null をポップし、インデックス 1 のローカル変数 a に保存します
2: new a StringBuilder
5: new によって以前に作成されたスペースをコピーし、オペランド スタックにプッシュします
6: 初期化の呼び出しが進行中です
9: 結果をオペランドスタックに保存します
10: StringBuilder.append(java/lang/Object)を呼び出します
13: "456"をスタックの先頭にプッシュします
15: StringBuilder.append(java/lang /String)
18: toString 関数を実行します
上記の分析から、最終的に最初に StringBuilder オブジェクトを生成し、後続の "+" 演算子はすべて StringBuilder.append() の "+" を呼び出していることがわかります。これは、オブジェクトを追加するときにオブジェクトを String に変換するために
public static String valueOf(Object obj) { return (obj == null) ? "null" : obj.toString(); }
が呼び出される理由として、上記のサンプル プログラムが実行後に null456 になる理由を説明できます。
なぜ JAVA は演算子のオーバーロードをサポートしないのですか?
C++ と同様に、クラスは演算子のオーバーロードを制限するための標準がないため、個人的には難しい問題になると思います。確かに、オーバーロードによってセマンティックな違いが発生し、可読性が大幅に低下するため、Java で演算子のオーバーロードを削除する機能は、その高度なオブジェクト指向の性質と非常に一致しています。したがって、この問題については深く考えないでください。
追記
これらは開発プロセスでよく使用されるものですが、通常の開発プロセスではそれほど深く掘ることはなく、当然のこととして認識されます。発見されないケース。