日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java 泛型 泛型的约束与局限性

發(fā)布時間:2023/12/4 java 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 泛型 泛型的约束与局限性 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

不能用基本類型實例化類型參數(shù)

不能用類型參數(shù)代替基本類型:例如,沒有Pair,只有Pair,其原因是類型擦除。擦除之后,Pair類含有Object類型的域,而Object不能存儲double值。這體現(xiàn)了Java語言中基本類型的獨立狀態(tài)。

運行時類型查詢只適用于原始類型(raw type)

運行時:通常指在Classloader裝載之后,JVM執(zhí)行之時

類型查詢:instanceof、getClass、強制類型轉(zhuǎn)換

原始類型:即(raw type),泛型類型經(jīng)編譯器類型擦除后是Object或泛型參數(shù)的限定類型(例如Pair,Comparable就是T的限定類型,轉(zhuǎn)化后泛型的原始類型就是Comparable,所以Pair類不帶泛型是Pair),即Pair類含有Comparable類型的域

JVM中沒有泛型

if(a instanceof Pair<String>) //ERROR,僅測試了a是否是任意類型的一個Pair,會看到編譯器ERROR警告if(a instanceof Pair<T>) //ERRORPair<String> p = (Pair<String>) a;//WARNING,僅測試a是否是一個PairPair<String> stringPair = ...; Pair<Employee> employeePair = ...; if(stringPair.getClass() == employeePair.getClass()) //會得到true,因為兩次調(diào)用getClass都將返回Pair.class//加入Java開發(fā)交流君樣:756584822一起吹水聊天

不能創(chuàng)建參數(shù)化類型的數(shù)組(泛型數(shù)組)

參數(shù)化類型的數(shù)組:指類型帶有泛型參數(shù)的數(shù)組,也即泛型數(shù)組,如Pair[] 、 T[]

不能實例化參數(shù)化類型的數(shù)組,例如:

Pair<String> table = new Pair<String>[10]; //ERROR

在這里我們假設可以實例化,那么經(jīng)編譯器類型擦除后,table的類型是Pair[],我們再讓它協(xié)變?yōu)镺bject[]:

Object[] objArray = table;

而一般來說,數(shù)組會記住他的元素類型Pair,我們?nèi)绻噲D存儲其他類型的元素,就會拋出異常(數(shù)組存儲檢查),例如:

objArray[0] = "Hello"; //ERROR--component type is Pair

但是,對于泛型類型Pair,類型擦除會使這種不同類檢查機制無效,這就是不能實例化泛型數(shù)組的原因!

objArray[0] = new Pair<Employee>(); //如果泛型機制允許我們實例化數(shù)組,那么這一步就沒理由出錯了! //而這違背了我們的初衷(限定類型)

數(shù)組存儲只會檢查擦除后的類型,又因為Java語言設計數(shù)組可以協(xié)變,所以可以通過編譯
能夠通過數(shù)組存儲檢查,不過仍會導致一個類型錯誤,故不允許創(chuàng)建參數(shù)化類型的數(shù)組
注意,聲明類型為Pair[]的變量是合法的,只是不能創(chuàng)建這些實例(我們應該直接用new Pair[10]{…}來初始化這個變量)

泛型數(shù)組的間接實現(xiàn):

通過泛型數(shù)組包裝器,如ArrayList類,維護一個Object數(shù)組,然后通過進出口方法set、get來限定類型和強制轉(zhuǎn)換數(shù)組類型,從而間接實現(xiàn)泛型數(shù)組,

例如:ArrayList: ArrayList<Pair<T>>、ArrayList<T>

不能實例化類型變量T

即不能使用new T(..) , new T[..] 或 T.class這樣的表達式中的類型變量
例如: public Pair() { first = new T(); } //ERROR!類型擦除將T改變成Object,調(diào)用非本意的new Object()
不能使用new T(..)
但是,可通過反射調(diào)用Class.newInstance方法來構(gòu)造泛型對象(要注意表達式T.class是非法的)

public static <T> Pair<T> makePair(Class<T> cl){try{ return new Pair<>(cl.newInstance() , cl.newInstance()); }catch(Exception ex) { return null; } } //加入Java開發(fā)交流君樣:756584822一起吹水聊天 //這個方法可以按照下列方式調(diào)用: Pair<String> p = Pair.makePair(String.class);

注意:Class類本身是泛型。String.class是一個Class的實例,因此makePair方法能夠推斷出pair的類型
不能使用new T[…]

解決方案:使用泛型數(shù)組包裝器,例如ArrayList
然而,當在設計一個泛型數(shù)組包裝器時,例如方法minmax返回一個T[]數(shù)組,則泛型數(shù)組包裝器無法施展,因為類型擦除,return (T [])new Object是沒有意義的強轉(zhuǎn)不了。此時只好利用反射,調(diào)用Array.newInstance:

import java.lang.reflect.*; ... public static <T extends Comparable> T[] minmax(T... a){T[] mm = (T[]) Array.newInstance(a.getClass().getComponentType() , 2); ... }

【API文檔描述】public Class<?> getComponentType() 返回表示數(shù)組組件類型的 Class。如果此類不表示數(shù)組類,則此方法返回 null。
而ArrayList類中的toArray方法的實現(xiàn)就麻煩了

public Object[] toArray() 無參,返回Object[]數(shù)組即可  public Object[] toArray() {return Arrays.copyOf(elementData, size);}

【API文檔描述】public static T[] copyOf(T[] original,int newLength)
  復制指定的數(shù)組,截取或用 null 填充(如有必要),以使副本具有指定的長度。對于在原數(shù)組和副本中都有效的所有索引,這兩個數(shù)組將包含相同的值。對于在副本中有效而在原數(shù)組無效的所有索引,副本將包含 null。當且僅當指定長度大于原數(shù)組的長度時,這些索引存在。所得數(shù)組和原數(shù)組屬于完全相同的類。
public T[] toArray(T[] a) a - 要存儲列表元素的T[]數(shù)組(如果它足夠大)否則分配一個具有相同運行時類型的新數(shù)組,返回該T[]數(shù)組

@SuppressWarnings("unchecked")public <T> T[] toArray(T[] a) {if (a.length < size)// Make a new array of a's runtime type, but my contents:return (T[]) Arrays.copyOf(elementData, size, a.getClass()); //a.getClass()得運行時目的數(shù)組的運行時類型//加入Java開發(fā)交流君樣:756584822一起吹水聊天System.arraycopy(elementData, 0, a, 0, size);if (a.length > size)a[size] = null;return a;}

【API文檔描述】
public static <T,U> T[] copyOf(U[] original,int newLength, Class<? extends T[]> newType)
復制指定的數(shù)組,截取或用 null 填充(如有必要),以使副本具有指定的長度。對于在原數(shù)組和副本中都有效的所有索引,這兩個數(shù)組將包含相同的值。對于在副本中有效而在原數(shù)組無效的所有索引,副本將包含 null。當且僅當指定長度大于原數(shù)組的長度時,這些索引存在。所得數(shù)組屬于 newType 類。
泛型類的靜態(tài)上下文中類型變量無效

泛型類不能在靜態(tài)域或靜態(tài)方法中引用類型變量

public class Singleton<T>{private static T singleInstance; //ERRORpublic static T getSingleInstance(){...} //ERROR }

類型擦除后只剩下Singleton類,因為靜態(tài)所以他只包含一個singleInstance域,如果能運行則以Singleton類為模板生成不同類型的域,因此產(chǎn)生了沖突

不能throws或catch泛型類的實例(有關(guān)異常)

泛型類繼承Throwable類不合法,如public class Problem<T> extends Exception {...}//ERROR 不能通過編譯
catch子句不能使用類型變量

public static <T extends Throwable> void doWork(Class<T> t){try{do work}catch (T e){ // ERRORLogger.global.info(...)} }

不過,在異常規(guī)范中使用類型變量是允許的:

public static <T extends Throwable> void doWork(T t) throws T { //此時可以throws Ttry{//加入Java開發(fā)交流君樣:756584822一起吹水聊天do work}catch (Throwable realCause){ //捕獲到具體實例t.initCause(realCause); throw t; //這時候拋具體實例,所以throw t 和 throws T 是可以的!} }

此特性作用:可以利用泛型類、類型擦除、SuppressWarnings標注,來消除對已檢查(checked)異常的檢查,
unchecked和checked異常: Java語言規(guī)范將派生于Error類或RuntimeException的所有異常稱為未檢查(unchecked)異常,其他的是已檢查(checked)異常

  • Java異常處理原則:必須為所有已檢查(checked)異常提供一個處理器,即一對一個,多對多個
@SuppressWarnings("unchecked") //SuppressWarning標注很關(guān)鍵,使得編譯器認為T是unchecked異常從而不強迫為每一個異常提供處理器 public static <T extends Throwable> void throwAs(Throwable e) throwsT{ //因為泛型和類型擦除,可以傳遞任意checked異常,例如RuntimeException類異常throw (T) e; }

假設該方法放在類Block中,如果調(diào)用 Block.throwAs(t); 編譯器就會認為t是一個未檢查的異常

public abstract class Block{public abstract void body() throws Exception;public Thread toThread(){return new Thread(){public void run(){try{body();}catch(Throwable t){Block.<RuntimeException>throwAs(t);}//加入Java開發(fā)交流君樣:756584822一起吹水聊天}};}@SuppressWarnings("unchecked")public static <T extends Throwable> void throwAs(Throwable e) throws T{throw (T) e ;} }

再寫個測試類

public class Test{public static void main(String[] args){new Block(){public void body() throws Exception{//不存在ixenos文件將產(chǎn)生IOException,checked異常!Scanner in = new Scanner(new File("ixenos"));while(in.hasNext())System.out.println(in.next());}//加入Java開發(fā)交流君樣:756584822一起吹水聊天}.toThread().start();} }
  • 啟動線程后,throwAs方法將捕獲線程run方法所有checked異常,“處理”成unchecked
    Exception(其實只是騙了編譯器)后拋出;

有什么意義?正常情況下,因為run()方法聲明為不拋出任何checked異常,所以必須捕獲所有checked異常并“包裝”到未檢查的異常中;意義:而我們這樣處理后,就不必去捕獲所有并包裝到unchecked異常中,我們只是拋出異常并“哄騙”了編譯器而已
注意擦除后的沖突

Java泛型規(guī)范有個原則:“要想支持擦除的轉(zhuǎn)換,就需要強行限制一個泛型類或類型變量T不能同時成為兩個接口類型的子類,而這兩個接口是統(tǒng)一接口的不同參數(shù)化”
注意:非泛型類可以同時實現(xiàn)同一接口,畢竟沒有泛型,很好處理

class Calender implements Comparable<Calender>{...}class GGCalender extends Calender implements Comparable<GGCalender>{...} //ERROR

在這里GGCalender類會同時實現(xiàn)Comparable 和 Comparable,這是同一接口的不同參數(shù)化

總結(jié)

以上是生活随笔為你收集整理的Java 泛型 泛型的约束与局限性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 四虎综合网 | 亚洲女人天堂av | 国产情侣露脸自拍 | 麻豆视频免费在线 | 亚洲乱码国产乱码精品 | 成人网久久 | 亚洲第一av网站 | av色哟哟| 黄色大片在线播放 | 最近免费中文字幕中文高清百度 | 在线观看黄色免费视频 | a视频在线看 | 欧美激情综合五月色丁香 | 国产精品三级视频 | 妺妺窝人体色www在线小说 | 欧美在线观看成人 | 青青草成人影视 | 亚洲精品鲁一鲁一区二区三区 | 成人免费高清在线观看 | 丰满多毛的大隂户视频 | wwwxxx亚洲| 欧美日韩国产在线播放 | 亚洲人人人| 日韩系列在线 | 国产精品久久伊人 | 黄色aaaa| 欧美国产日本 | 制服一区二区 | 五月天婷婷综合网 | 青娱网电信一区电信二区电信三区 | 久久久久18| 欧美黄色小视频 | 国产欧美一区二区三区在线 | 极品一区| 久久人人超碰 | 欧州一区 | 日本不卡免费 | 欧美精品啪啪 | 精品国产www | 麻豆高清视频 | 亚瑟av| 自拍偷拍1 | 麻豆区1免费 | 欧美日韩精品久久 | 91黄在线看 | 最近中文字幕在线mv视频在线 | 国产一级久久 | 黄色大片免费的 | 成人在线午夜 | 轻轻色在线观看 | 国产精品无码人妻一区二区在线 | 成年人黄色一级片 | 亚洲色图综合 | 亚洲成人精 | 成人免费在线观看网站 | 国产精品一区二区无码对白 | 欧美丰满熟妇bbbbbb百度 | 亚洲一区二区在线免费 | 91亚洲国产成人精品一区二区三 | 少妇野外性xx老女人野外性xx | 国产精品久久av无码一区二区 | 浪浪视频在线观看 | 制服丝袜快播 | 亚洲精品久久久久久无码色欲四季 | 桃谷绘里香在线观看 | 国产午夜三级 | 亚洲美女偷拍 | 天天操天天爽天天干 | 欧美精品久久久久久久自慰 | 欧美日韩久久久久久 | 日韩不卡免费视频 | 黑帮大佬和我的三百六十五天 | 俺去草 | 日韩欧美精品免费 | 中文字幕一区二区三区不卡 | 日韩黄色影视 | 日韩一卡二卡在线 | 精品日韩av | 日韩精品麻豆 | 欧美日色 | 天天激情综合 | 中国男女全黄大片 | 黄网站欧美内射 | 超碰综合 | 国产九九精品视频 | 重囗另类bbwseⅹhd | 欧美电影一区二区三区 | 六月色 | 欧美另类在线观看 | av尤物 | 久久精品黄色片 | 无码任你躁久久久久久久 | 成人欧美日韩 | 熟女俱乐部五十路六十路av | 夜夜爽av福利精品导航 | 成人黄色小说视频 | 伊人在线 | 日日摸日日添日日碰9学生露脸 | 午夜视频观看 |