事件起因
在做一個類型轉換時遇到了下面的異常:
是說不能把 Integer 類型強制轉換成 String 類型。
我的測試代碼大概是這個樣子:
public static void testClassCastException() {
Integer i1 = Integer.valueOf(getT()); // ① 拋異常
Integer i2 = (Integer) getT(); // ② 正常
Integer i3 = Integer.valueOf(getT().toString()); // ③ 正常
}
private static <T> T getT() {
return (T) new Integer(10);
}
// ①和③的不同在於Integer.valueOf()裏的參數的類型,其實Integer.valueOf()方法就是需要String類型的,所以我們直接用Integer類型當然在底層是不識別的。
// ①和②的不同在於類型轉換的方式,這個就引申出下面這個問題了。
(String)、toString、String.valueOf 的區別
- toString()
toString()是在 Object 中定義的,因此,任何繼承 Object 的類都具有這個方法。
在 API 中 toString()被描述爲:
返回該對象的字符串表示。通常,toString 方法會返回一個“以文本方式表示”此對象的字符串。結果應是一個簡明但易於讀懂的信息表達式。建議所有子類都重寫此方法。
Object 類的 toString 方法返回一個字符串,該字符串由類名(對象是該類的一個實例)、標記符“@”和此對象哈希碼的無符號十六進制表示組成。換句話說,該方法返回一個字符串,它的值等於:getClass().getName()+’@’+Integer.toHexString(hashCode())
我們在定義一個類的時候可以重寫繼承自 Object 的 toString()方法,以此來表示該對象的基本信息。
但是,使用 toString()的對象不能爲 null,否則會拋出異常 java.lang.NullPointerException。
- String.valueOf()
String.valueOf()解決了 toString()使用對象不能爲空的問題,實際上,該方法在底層還是使用了 toString()。如下源碼:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
值得注意的是,如果使用對象爲 null,返回的結果是字符串”null”,而不是對象 null。
在很多時候使用 String.valueOf()比使用 toString()更能減少報錯的機會,因爲不用考慮是否爲 null 的情況。但是,也要特別注意:if(String.valueOf(o) == null){…}這樣的代碼肯定就回有問題,因爲永遠不會得到執行。
- (String)
(String)區別於上面兩種方法,因爲它是強制轉換。
每個對象在創建的時候就已經確定了類型不能改變,所謂的強制轉換隻是表面上將其轉換成了另一種類型,就相當於 A 被當成了 B 使用,如果 A 能夠被當成 B,那一切沒有問題,但是 A 做不了 B,就只能拋出異常,說我做不到。
Integer o = new Integer(100);
System.out.println((String)o);
如上代碼編譯時就會報錯:Cannot cast Integer to String,說明 Integer 不能通過強制轉換成 String。
而我們一開始的代碼:
Object x = new Integer(0);
System.out.println((String)x);
在編譯時沒錯,運行時拋出異常。這是因爲 x 在表面上是 Object,實際上是 Integer。而 Object 是可以通過強制轉換成爲 String 的。所以,在編譯的時候,x 被當成了 Object,大家相安無事,真正運行的時候,x 被查出來是 Integer,理所當然就拋出了 ClassCastException。
最安全的方法:instanceof
取到的對象進行類型轉換如果不知道具體會是什麼類型的,可以通過instanceof
關鍵字來檢查改對象屬於哪個類型的,再具體去進行某些業務。
PS:
a instanceof b
的結果和b.class.isInstance(a)
的結果是一致的,可以實現相同的功能,完全等價。
爲什麼在 Java 裏不能將 Integer 強制轉換成 String
因爲 String
和 Integer
不是在同一個對象階層。
Object
/ \
/ \
String Integer
當你嘗試強制轉換時,僅僅會在同一個對象階層轉換。比如:
Object
/
/
A
/
/
B
在這種情況,(A)objB
或者 (Object)objB
或者 (Object)objA
可以進行轉換。
正如其他人已經提到,將integer
轉換成String
可以使用以下方法:
基本類型的整型時使用:String.valueOf(integer)
或者Integer.toString(integer)
來轉換成String
。
Integer
對象型時使用:Integer.toString()
轉換成String
參考:
翻譯|爲什麼在 Java 裏不能將 Integer 強制轉換成 String | PostgreSQL DBA
java.toString() ,(String),String.valueOf 的區別 _java_springk 的專欄-CSDN 博客