java泛型 例子_关于 Java 泛型的一些有趣的例子
有以下的代碼:
1 try{2 ArrayList lstA = new ArrayList();3 ArrayList lstB = new ArrayList();4
5 //ArrayList c = (ArrayList)lstA;
6
7 Object d =lstA;8 ArrayList e = (ArrayList)d;9 System.out.println("e.toString=" +e.toString());10
11 List f =lstA;12 System.out.println("f.toString=" +f.toString());13
14 if (lstA.getClass() ==lstB.getClass()) {15 System.out.println("lstA.class == lstB.class");16 }else{17 System.out.println("lstA.class != lstB.class");18 }19
20 String[] g = {"","2"};21 Object[] h =(Object[])g;22 System.out.println("h.toString=" +h.toString());23 } catch(Exception ex) {24 System.out.println("cast error!--" +ex.getMessage());25 }
運行以上代碼,估計會輸出什么?會產生異常嗎?
實際上,這些代碼都能正常運行。
先看看被注釋掉的第 5 行:
ArrayList c = (ArrayList)lstA;
這行會產生編譯錯誤,所以被注釋掉了。可是換一種方式卻可以通過編譯器的檢查,也就是接下來的7-9行:
Object d =lstA;
ArrayList e = (ArrayList)d;
System.out.println("e.toString=" + e.toString());
這幾行代碼不光是騙過編譯器,也能夠正常運行。
繼續看接下來的 11-12 行:
List f =lstA;
System.out.println("f.toString=" + f.toString());
與前面 7-9 行的有所不同的是,前面是對“類型參數”做了轉換,而此處是類型本身變了,即將 ArrayList 轉為其超類接口 List ,這能行嗎?
運行便知!OK,執行通過!
繼續看看接下來的 14-18 行:
if (lstA.getClass() ==lstB.getClass()) {
System.out.println("lstA.class == lstB.class");
}else{
System.out.println("lstA.class != lstB.class");
}
猜猜這里輸出的結果是什么?
答案是:
"lstA.class == lstB.class"
為什么呢?難道 lstA 和 listB 是同一個類型,可是他們明明一個是 ArrayList,一個是ArrayList 。
原來這就是泛型的障眼法。
與 C# 的泛型不同,java 的泛型實際上更像是個語法上的東西,在運行時是沒有“泛型”的存在的,運行時 lstA 和 lstB 的類型都是 ArrayList (或者說等同 ArrayList)。
我們再看看最后的 20-22 行:
String[] g = {"","2"};
Object[] h=(Object[])g;
System.out.println("h.toString=" + h.toString());
這和前面的 11 行類似,對于數組同樣也行得通。當然這跟泛型沒什么關系,這種稱為“協變”,只是形式上與一些泛型的操作類似,所以放在一起比照。
以上全部代碼在我本機運行的輸出結果如下:
e.toString=[]
f.toString=[]
lstA.class == lstB.class
h.toString=[Ljava.lang.String;@e09713
再看看另外的一個例子:
1 public static voidmain(String[] args) {2 try{3 testCaster1(SQLException.class);4 } catch(SQLException e) {5 System.out.println(String.format("SQLException=[%s]--%s", e.getClass().getName(), e.getMessage()));6 } catch(Exception e) {7 System.out.println(String.format("Exception=[%s]--%s", e.getClass().getName(), e.getMessage()));8 }9
10 try{11 testCaster2(SQLException.class);12 } catch(SQLException e) {13 System.out.println(String.format("SQLException=[%s]--%s", e.getClass().getName(), e.getMessage()));14 } catch(Exception e) {15 System.out.println(String.format("Exception=[%s]--%s", e.getClass().getName(), e.getMessage()));16 }17 }18
19
20 private static void testCaster1(Class clazz) throwsE{21 try{22 throw new SQLException("測試拋出的SQL錯誤。");23 } catch(Throwable e) {24 throw(E)e;25 }26 }27 private static void testCaster2(Class clazz) throwsE{28 try{29 throw new IOException("測試拋出的IO錯誤。");30 } catch(Throwable e) {31 throw(E)e;32 }33 }
兩個泛型方法 testCaster1 和 testCaster2 的邏輯是一樣,用泛型 E 定義了 throws 拋出的異常類型,同時在內部捕捉 Throwable 并將其轉換為聲明的泛型參數返回。
等等!!
細心的你是不是發現了什么不對勁的地方?...
是的,第 24 行和 31 行,明顯異常類型 E 是泛型,調用者指定的具體類型是不確定的,而這兩個方法一個拋出 SQLException,一個拋出 IOException,
那接下來的轉換要引發 ClassCastException 了吧?
不過答案是否定的!它們運行得很好。
看 main 方法中的 2-8 行,調用 testCaster1 拋出的 SQLException,最終被 catch(SQLException e) 捕捉到。
再看接下來的 10-16 行,調用 testCaster2 拋出的 IOException,最終被 catch(Exception e) 捕捉到。
在 testCaster2 的內部拋出的 IOException 似乎并沒有按照調用者指定的泛型參數 SQLException 做強制轉換,因為并沒有?ClassCastException 發生。
哈哈,這又是泛型的障眼法!
全部輸出結果如下:
SQLException=[java.sql.SQLException]--測試拋出的SQL錯誤。
Exception=[java.io.IOException]--測試拋出的IO錯誤。
總結
以上是生活随笔為你收集整理的java泛型 例子_关于 Java 泛型的一些有趣的例子的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python扫描局公网ip_公网IP检测
- 下一篇: Java jdbctemplate赋值_