java提供的“+”運算符,如iteger+string,從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);
}
}
這個程式很簡單就是一個integer和string的“+”運算表達式。運作結果: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[]);
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一個stringbuilder
5:複制之前new出來的空間并将其壓入操作數棧
6:調用進行初始化
9:将結果儲存到操作數棧
10:調用stringbuilder.append(java/lang/object)
13:将“456”壓入棧頂
15:stringbuilder.append(java/lang/string)
18:執行tostring函數
從上面的分析我們可以看到其最終是先生成了一個stringbuilder對象,之後的“+”操作符都是調用了stringbuilder.append()進行“+”的。這就可以解釋上面示例程式運作後為什麼是null456了,append
object的時候調用了
public static string valueof(object obj) {
return (obj == null) ? "null" : obj.tostring();
将object轉化為string了。
為什麼java不支援操作符重載
像c++中類對操作符進行了重載,個人覺得會操作維護難得問題,因為操作符重載沒有一個标準來限制大家都可以想當然的進行重載會造成語義相差大,可讀性嚴重降低,是以java中去掉操作符重載這個特性和他的進階面向對象很相符。so,不糾結這個問題。
後記
這都是在開發過程中會經常使用的一些東西但是可能在平時開發過程中沒有挖的這麼深入,都想當然了,後面可以嘗試不斷挖掘這些不被發現的小case。
作者:liutxer
來源:51cto