關於List泛型的強制轉換


當我們從數據庫中查詢出一些數據,有時返回的結果可能是List<Object>類型,而我們清楚的知道它的准確類型是List<User>,可能我們想直接的去進行類型的轉換,你可能會這么寫:

//DbUtils.list("from User")返回是List<Object>類型

List<User> listUser= (List<User>)DbUtils.list("from User");

然而編輯器提示不可轉換,這是為什么啊?我們項目開發中常常像下面這樣去使用強轉都可以的啊:

Object o= new Object();

User u= new User();

//向下轉型

u= (User)o;

o= u;

看看上面的代碼,是很正常的轉換啊,即使父類向下轉型為子類也是沒問題的盡管存在類型安全的隱患,以下為我的推算,因為Object是所有類型的父級,所以任何對象都可以去轉換成Object,因為有了這個繼承的特性,有可能Object指向了一個User,而我們又需要使用這個User的方法,所以它支持存在安全隱患的強制向下轉型,盡管存在安全隱患,但只要我們編碼時稍微注意就可避免此隱患,因為我們知道這個Object指向的是一個User,所以有繼承關系的向下類型轉換是可避免的安全隱患。

但為什么List<User>和List<Object>轉就不行了呢?

我們可以把List<User>和List<Object>想象為兩個特殊(類似基本類型的存在)的類型(此處暫不知道如何解釋,因為我對java的底層泛型處理這塊知識並不了解,暫時先去這么理解),就例如:

String s= "a";

Integer i= 12;

i= (Integer)s;

你會發現字符串不能強轉到整形,編譯器禁止這么做是為了讓類型更加安全,如果任何類型之間都能互相轉換的話那將會導致類型的不安全,因為他們之間沒有繼承關系,如果貿然去轉換將會發生不可避免的類型安全隱患,但是他們的父類都是Object,我們可以通過使用Object作為橋梁來間接轉換:

String s= "a";

Integer i= 12;

Object o= s;

i= (Integer)o;

這樣雖然編譯期並沒有報錯,但運行期將會報類型轉換異常,所以我們使用時一定要小心,只能強轉給它的原類型。

 

既然我們無法直接轉換,而又不想一個元素一個元素的去轉類型,那么我們就間接的去轉換吧,下面是間接轉換的幾種方式:

//1,此方法不可行,雖然編譯期不報錯,但運行期會轉換失敗,數組轉換失敗的原因與泛型強轉失敗應該同理,都是特殊(類似基本類型的存在)的類型,數組的強轉在編譯期檢查不出來,使用的時候要注意這點。

List<User> listUser= Arrays.asList((User[])DbUtils.list("from User").toArray());

//2

List<User> listUser= Arrays.asList(DbUtils.list("from User").toArray(new User[0]));

//3,此方法不可行,雖然編譯期不報錯,但運行期會轉換失敗,數組轉換失敗的原因與泛型強轉失敗應該同理,都是特殊(類似基本類型的存在)的類型,數組的強轉在編譯期檢查不出來,使用的時候要注意這點。

List<User> listUser= new LinkedList<User>();
Collections.addAll(listUser, (User[])DbUtils.list("from User").toArray());

//4

List<User> listUser= new LinkedList<User>();
Collections.addAll(listUser, DbUtils.list("from User").toArray(new User[0]));

//5,利用萬物皆Object的思想來使用強轉

List<User> listUser= (List<User>)(Object)DbUtils.list("from User");

 //6

Object object= DbUtils.list("from User");
List<User> listCart= (List<User>)object;

我比較喜歡2和4的轉換方式。

注意:基本類型的強轉和引用類型的強轉是有區別的,但這種區別很好區分,下面舉一個小例子:

//1

int i= 1;

long l= 10;

//可行

i= (i)l;

//2

Integer i= new Integer(1);

Long l= new Long(10);

//不可行

i= (Integer)l;

 

以上觀念為經驗總結,並非總是正確的,如果你感覺我的見解有誤,請及時糾正我。

求解釋:

Object[] os= new Object[]{"a","b","c"};
String[] ss= (String[]) os;
System.out.println(ss);

即使利用萬物皆對象的思想也是一樣的結果。

Object[] os= new Object[]{"a","b","c"};

Object o= os;
String[] ss= (String[]) o;
System.out.println(ss);

為什么轉換異常?

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM