簡體   English   中英

Java 類型轉換。 (String), .toString() 和 “” + int 背后的邏輯

[英]Java type casting. Logic behind (String), .toString() and “” + int

Java 是一種強類型語言。 因此,編譯代碼中的錯誤更少,可讀性更好,但編碼速度較慢。 因此,需要顯式類型轉換,這部分很清楚。

這些片段之間有什么區別:

(String)myInt // obviously doesn't compile
Integer.toString(myInt)
"" + myInt

是單純的歷史原因,還是背后另有隱情?
哪種方法合適?

如前所述, (String) myInt是一個類型轉換。 在 Java 中,我們可以在原語中進行轉換,也可以在對象層次結構中向上轉換。 由於int是一個原始類型而String是一個對象,我們有一個問題。 甚至自動裝箱也無法解決這個困境,因為IntegerString並不處於繼承關系中。 因此, (String) myInt導致編譯錯誤是完全合理的。

Integer.toString(myInt)"" + myInt是相同的。 但是,具體情況有所不同。

執行Integer.toString(myInt) ,會構造一個新的String ,其中包含myInt的字符串表示。

當執行"" + myInt ,Java 首先構造一個全局String常量,其值為"" (這是由 JVM 完成的,我們沒有看到這個1 )。 詞法分析器在+的右側需要一個String ,因為它在+的左側找到了一個String 對於原語,JVM“知道”如何將它們轉換為String 對於對象,調用toString() 由於Object具有此方法並且每個類(至少隱式地)從Object派生,因此保證每個對象都有一個toString()方法。 這是構造的第二個String 由於String s 是不可變的,JVM 可能會創建第三個String ,表示前兩個String s 2的串聯。


結語

然后,在執行時,JIT 編譯器發生故障,其中大部分可能無關緊要,因為這兩種變體的 JIT 優化版本可能看起來相同。 或者不是。 或者也許只是有時。 JIT 做一些有趣的事情。 所以最終這更像是個人風格而不是表現的問題:)


1這其實是一個謊言。 寫作時

String s1 = "";
String s2 = "";
System.out.println(s1 == s2);

人們會觀察到結果為true ,而預期為false 這是因為 JVM 為所有String常量創建了一個池以節省一些內存。

2 JVM 很可能“識別”到something + "" == "" + something == something ,因此不會創建第三個String 我既沒有測試也沒有研究這個。

我自己更喜歡String.valueOf(int) ,但是是的,有多種途徑可以到達那里。

在一般情況下,如果你的轉換intString孤立,想要Integer.toString(int) String.valueOf(int)或類似的。

您的"" + myInt效率將明顯低於上述(盡管通常無關緊要):它編譯為創建一個新的StringBuilder ,然后將""附加到它,然后將int附加到它(它調用上面的方法首先將其轉換為字符串),然后從StringBuilder獲取String 因此,雖然您可以將其作為整體串聯操作的一部分來執行,但就其本身而言,它非常糟糕。

您的(String)示例不起作用:您不能僅將int轉換為String ,您將收到編譯時“類型不兼容”錯誤。

這是一種“正式”重載+運算符的語言特性,使得

"" + myInt

被編譯為:

new StringBuilder().append("").append(myInt).toString();

StringBuilder#append() (最終)調用String.valueOf()來呈現myInt

這個功能大概是因為如果他們不這樣做,就沒有人會使用這種語言——這太痛苦了。

(String) - 這僅適用於字符串,所以如果你有這個:

Object test = "test";
String test2 = (String) test;

它將起作用(因為Object測試將是String類型)。

如果你有這樣的事情:

Integer test = new Integer(2);
String test2 = (String) test;

你得到ClassCastException

Integer.toString(myInt)

這是它的作用:

 public static String  toString(int i) {
         if (i == Integer.MIN_VALUE)
             return "-2147483648";
         int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
         char[] buf = new char[size];
         getChars(i, size, buf);
         return new String(0, size, buf);
     }

它只是將您的數字按字符轉換為字符串。

"" + myInt

這將告訴編譯器您想將事物連接為字符串,而不是添加兩個數字(因為字符串是第一個,它將與連接字符串一起使用)。 myInt 會轉成字符串,或者如果是一個對象,它會從中調用toString()方法。

另外,請確保您閱讀了 JVM 中的字符串池,以了解它在這里的作用。 在這種情況下,它最終可能會創建大量臨時字符串(如果您有很多+ ;請使用StringBuilder避免這種情況)。

首先,讓我們比較(String)valval.toString()

這兩個語句的主要區別在於,轉換是由編譯器進行的,toString()方法通常由程序員實現。 也就是說,只有當 value 擴展String並且您可以實現任何類的toString() ,您才能進行轉換。 toString()就像任何其他方法一樣工作,並且沒有(幾乎)特別之處。

現在讓我們來看看""+int 我個人認為這是反模式,因為它被編譯成效率極低的代碼。 大量無用的對象被創建; 簡而言之:結果類似於用StringBuilder手動連接幾個字符串文字。 此外,在像""+var var不擴展String這樣的語句中,隱式調用了toString()

我希望這很清楚。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM