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