當我們從數據庫中查詢出一些數據,有時返回的結果可能是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);
為什么轉換異常?