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

歡迎訪問 生活随笔!

生活随笔

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

java

Java 泛型(1):基本原理

發布時間:2025/3/15 java 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 泛型(1):基本原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.1????? 擦除

15.7例子

Java的泛型是同伙擦除來實現的,在泛型代碼內部,無法獲得任何有關泛型參數類型的信息(這一點有別于C++等實現),這意味著你在使用泛型時,無法知道任何類型信息,只知道你在使用一個對象,因此List<String>和List<Integer>在運行時事實上是相同的類型。

1.1.1??????? C++的實現

15.7.1例子

C++的實現與Java實現不同,當你實例化模板時,C++編譯器會進行檢查,模板代碼知道參數類型,所以如果調用了類型的某些方法,將由編譯器在編譯時進行檢查

?

1.1.2??????? 為何采用擦除

泛型不是Java出現時就有的組成部分,而是中途加入的,為了向下兼容許多現有的代碼和類文件,并且保持其原有的含義,所以采用了擦除這一解決方案,允許非泛型和泛型代碼共存。

?????? 必須意識到,擦除并不是實現泛型最好的技術,如果泛型出現在Java 1.0,那么將不會使用擦除來實現,而是使用具體化,這樣你就可以在類型參數上執行基于類型的操作和反射,擦除減少了泛型的泛化性,使得Java的泛型沒有本來設想的那么有用,但是泛型在Java中仍然是一個很有用的特性。

1.1.3??????? 擦除引入的問題

由于擦除的原因,Java的泛型不能用于顯示地引用運行時類型的操作,例如轉型、instanceof、new等操作。因為所有的參數類型都丟失了,在編寫泛型代碼時,必須時刻提醒自己,你只是看起來擁有了參數類型信息,例如:

Foo<Cat> f = new Foo<Cat>();

我們通常會認為,Foo的代碼應該知道操作的對象是Cat,而且從語法上也給人這樣的暗示:在Foo類中,所有的地方類型T都被替換成了Cat。但是事實卻完全不是這樣,你必須要知道,它只是一個Object。

?

?

1.2????? 邊界

邊界就是在泛型的參數類型上設置限制條件,比如<T extends Shape>等,使用邊界讓你可以強制規定泛型可以應用的類型。

??? 因為擦除了類型信息,導致我們只能調用那些Object的方法,但是,我們可以通過將這個參數限制為某個類型的子集,那么你就可以用這些類型子集的方法。我們可以通過繼承來消除邊界書寫上的冗余,如下例所示,通過繼承,在每個層次上添加邊界限制,在不斷的繼承中,T擁有了越來越多的成員。

public interface IGetName {public String getName();}public interface Weight {public int getWeight();}public class Shape {int x;int y;int z;}public class Cat<T> {T item;Cat(T item) {this.item = item;}}public class MyCat<T extends IGetName> extends Cat<T>{MyCat(T item) {super(item);}public String getMyCatName() {return item.getName();}}public class MyCats<T extends Shape & IGetName & Weight> extends MyCat<T> {MyCats(T item) {super(item);// TODO Auto-generated constructor stub }int getCatWeight() {return item.getWeight();}int getShape() {return item.x + item.y + item.z;}}

?

?

注意:在繼承中,T的作用域必須越來越窄,不能越來越寬,例如:IgetName接口在MyCat的類中已經作了限制,如果在MyCats的繼承中將IGetName去掉(class MyCats<T extends Shape & Weight> extends MyCat<T>),將會出現The type T is not a valid substitute for the bounded parameter <T extends IGetName> of the type MyCat<T>的錯誤,原因就是T的作用域變寬了(父類的T必須是繼承IGetName,而子類沒有這一限制)。

??? 在類型邊界限制中,不管是類還是接口都是使用extends,中間使用&分隔,同時需要注意的時,如果有類繼承,那么類必須寫在第一個,接口寫在第二個到第n個,<T extends 類 & 接口1 & 接口2 & 接口3 ...>。

1.3????? 泛型數組

1.3.1??????? 為什么Java不能創建泛型數組

擦除會移除參數類型信息,而數組必須知道他們所持有的確切類型,以強制保障類型安全

在Java中,Object[]數組可以是任何數組的父類,或者說,任何一個數組都可以向上轉型成它在定義時指定元素類型的父類的數組,這個時候如果我們往里面放不同于原始數據類型 但是滿足后來使用的父類類型的話,編譯不會有問題,但是在運行時會檢查加入數組的對象的類型,于是會拋ArrayStoreException:

String[]strArray=newString[20];Object[]objArray=strArray;objArray[0]=newInteger(1);// throws ArrayStoreException at runtime

?

因為Java的范型會在編譯后將類型信息抹掉,這樣如果Java允許我們使用類似Map<Integer,String>[]mapArray=newMap<Integer,String>[20];這樣的語句的話,我們在隨后的代碼中可以把它轉型為Object[]然后往里面放Map<Double, String>實例。這樣做不但編譯器不能發現類型錯誤,就連運行時的數組存儲檢查對它也無能為力,它能看到的是我們往里面放Map的對象,我們定義的<Integer, String>在這個時候已經被抹掉了,于是而對它而言,只要是Map,都是合法的。想想看,我們本來定義的是裝Map<Integer, String>的數組,結果我們卻可以往里面放任何Map,接下來如果有代碼試圖按原有的定義去取值,后果是什么不言自明。

?????? 如上原因,Java中不能創建泛型數組,一般的解決方案是在你想創建泛型數組的地方使用ArrayList。

1.3.2??????? 生成泛型數組的折中方法

?????? 有趣的是,雖然Java中不能創建泛型數組,但是你卻可以定義一個泛型數組的引用,而且編譯器不會產生任何警告,但是你卻永遠不能創建這個數組。

Foo<Cat> []f = new Foo<Cat>[SIZE]; //error Foo<Cat> [f]; //right

?????? 既然無法創建泛型數組,那么泛型數組的引用拿來干什么呢,考慮以下用法:

????????????? Foo<Cat> []f = (Foo<Cat>)new Object[SIZE];? //compile ok, run error

數組的每個元素應該持有相同的類型,那么通過創建一個Object的數組進行強轉成泛型數組是否可行呢?事實上以上代碼是可以編譯的,但是當你運行的時候,卻會拋出ClassCastException異常。原因是雖然我們將Object進行了強轉(所以編譯期不會報錯),但是在運行時它仍然是Object,所以引發了類異常。

?

事實上,生成泛型數組的唯一方式是創建一個被擦除類型的新數組,然后對其轉型,例如: T [] array;? array = (T[])new Object[SIZE]; 考慮以下例子,我們使用泛型數組來生成一個自己的簡單的數組:

class MyArray<T> {private T[] array;public MyArray(int size) {array = (T[])new Object[size];}public void set(T item, int n) {array[n] = item;}public T get(int n) {return array[n];}public T[] getArray( ) {return array;}public static void prt(String str) {System.out.println(str);}public static void main(String []args) {MyArray<String> my = new MyArray(3);my.set("a", 0);my.set("b", 1);my.set("c", 2);prt(my.get(1));//String[] o = my.getArray(); //run error Object[] o = my.getArray();prt(Arrays.toString(o));}}//out b[a, b, c]

?

?

注意:我們仍然不能使用T[] array = new T[SIZE];只能使用創建對象數組,然后強轉的方式,因為Object是任何類型的基類,所以我們可以將String類型的對象賦值到數組上,注意方法getArray(),它的返回值為T[],在main函數中,聲明的是<String>,所以我們嘗試將其賦予到String[]數組上,但是此時運行時發生了類型錯誤,這是因為本質上我們的數組還是Object[],所以在運行中試圖將一個Object[]賦值到String[],自然會發生異常。

?????? 事實上,更加穩妥的做法是將上述代碼中的數組聲明,更改成Object[] array,由于Java的擦除技術,所以我們運行的時候類型都會是Object,如果我們立刻將其轉型成T[],那么我們編譯期就會丟失數組的實際類型(Object),此時編譯器可能錯過一些潛在的錯誤檢查。另外一點,使用Object[]聲明可以隨時提醒我們,這個數組運行時是Object,而不是T[]。

?

1.3.3??????? 生成“真正的”泛型數組

仍然考慮上述的例子,如果我們將參數類型傳入進去,那么我們可以生成一個“真正的”泛型數組,通過反射技術,生成了實際傳入的參數類型(String)的數組,這樣array的實際類型就是String[],而不是上例的Object[],所以在main()中getArray()直接返回給String[]類型的引用沒有任何問題。

class MyArray<T> {private T[] array;public MyArray(Class<T> type, int size) {array = (T[])Array.newInstance(type, size);}public void set(T item, int n) {array[n] = item;}public T[] getArray( ) {return array;}public static void main(String []args) {MyArray<String> my = new MyArray(String.class, 3);my.set("a", 0);my.set("b", 1);my.set("c", 2);String[] o = my.getArray();System.out.println(Arrays.toString(o));}}

?

?

轉載于:https://www.cnblogs.com/LemonPi/p/11040252.html

總結

以上是生活随笔為你收集整理的Java 泛型(1):基本原理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 波多野结衣一区在线 | 成人手机视频在线观看 | 91精品看片 | 亚洲成人资源 | jizz成熟丰满日本少妇 | 麻豆视频在线观看免费网站黄 | 少妇色| 亚洲av无一区二区三区怡春院 | 香蕉av一区二区 | 国产精品无套 | 清清草在线视频 | 游戏涩涩免费网站 | 国产农村妇女精品 | sese久久 | 亚洲精品手机在线 | 韩日精品在线观看 | 相亲对象是问题学生动漫免费观看 | 日本一本一道 | 国产福利精品在线 | 国产a国产片国产 | 手机看片1024在线 | 一区二区三区免费在线观看视频 | 黄色成人av在线 | 成年人黄色免费视频 | 麻豆免费在线 | 久久网伊人 | 久久久毛片 | 日批视频| 双性娇喘浑圆奶水h男男漫画 | 欧美一区二区三区四 | 成人免费视频网站 | 丰满多毛的大隂户视频 | 欧洲人妻丰满av无码久久不卡 | 久久精品大全 | 麻豆蜜桃在线观看 | 国产午夜精品一区二区三区嫩草 | 亚洲五月综合 | 99人人爽 | 国产精品乱码久久久久久 | 国产免费又黄又爽又色毛 | 97人人草 | 4438激情网| 爽好多水快深点欧美视频 | 97日日夜夜| 大黄毛片| 手机看片日韩国产 | 性欧美又大又长又硬 | 日韩视频免费观看高清完整版 | 色婷婷国产精品久久包臀 | 波多野结衣欲乱上班族 | 国产农村妇女毛片精品久久麻豆 | 久久噜噜色综合一区二区 | 性爱视频免费 | 日韩和一区二区 | 国模婷婷| 91人妻一区二区三区蜜臀 | 香蕉av一区 | www,xxx69 japan| 精品少妇无码av无码专区 | 欧美人成在线视频 | 中文字幕一区二区三区人妻不卡 | 午夜色大片 | 亚洲最新在线观看 | 欧美福利在线视频 | av5566| 国产成人+综合亚洲+天堂 | 国产精品超碰 | 人妻互换一二三区激情视频 | 公妇借种乱htp109cc | 久久亚洲AV无码专区成人国产 | 小泽玛丽亚在线观看 | 99激情视频 | 超碰人人人人人人 | 国产男人天堂 | 亚洲女人天堂av | 激情文学久久 | 99久久99 | 亚洲aaaaaa | av最新网址 | 简单av在线 | 六月婷婷中文字幕 | 国产一区二区久久精品 | 综合色在线观看 | 第一av在线 | 男女在线观看 | 男男做性免费视频网 | 色天天干 | 久操不卡 | 欧美在线网址 | 亚洲一区二区免费在线观看 | 热99| www.色香蕉 | 日韩中文字幕视频在线 | 国产小视频在线观看免费 | 自拍偷拍五月天 | 色婷婷色婷婷 | 久久精品9 | 日本久久一级片 | 久草观看视频 |