<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
什麼是泛型?
泛型是在Java SE 1.5引入的的新特性,本質是引數化型別,也就是說所操作的資料型別被指定為一個引數。這種引數型別可以用在類、介面和方法的建立中,分別稱為泛型類、泛型介面、泛型方法。
簡而言之:<>泛型就是用來約束類、方法、屬性上的資料型別,比如
List<Integer> list = new ArrayList<Integer>();List<Integer> list = new ArrayList<Integer>();
new ArrayList這個集合的元素只能新增Integer型別。
為什麼需要泛型?
Java推出泛型之前,程式設計師可以構建一個Object型別的集合,該集合能夠儲存任何的資料型別,而在使用該 集合的時候,需要程式設計師明確知道每個元素的具體的型別並向下轉型,否則容易引發ClassCastException 類轉換異常。現在我們通過泛型就能解決這個問題,通過泛型<>我們就能夠約束這個集合插入的型別,就不需要再從Object型別轉換成子類型別。
泛型有什麼好處?
泛型的型別:
泛型可以定義在類上、父類別上、介面上、子類上、方法上、引數上、屬性上, 泛型型別是可以用任意字母來代替你需要傳遞的資料,一般為了可讀性,我們約定一般會寫:
那麼這麼多字母有什麼用呢?我們來看一段程式碼:這是一個普通的Student類:
package Test; public class Student { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
我們升級一下,把這個類定為String的泛型,意思是這個類只能接收String的型別:
public class Student<Stirng> { //重複的程式碼就不重寫了,和上面的是一樣 }
ok,這樣沒問題,但是我們想一想,如果直接就把這個類的泛型定義死了,如果後面需要在Student傳入Integer型別,我們就得重寫一個Student類,這樣程式碼的複用性不高,不符合程式設計思維,所以我們可以這樣:
public class Student<T> { private T t; public T getT() {return t;} public void setT(T t) {this.t = t;} }
然後當需要用什麼泛型的時候直接傳入即可:
Student<String> stu1 = new Student<>(); Student<Integer> stu2 = new Student<>(); Student<Double> stu3 = new Student<>();
測試:(接上面的程式碼)
public class Test { public static void main(String[] args) { //先使用Integer泛型,傳入100 Student<Integer> stu1 = new Student<>(100); Integer in = stu1.getT(); System.out.println(in); } }
輸出:100 (沒問題)
但是如果在定義為Integer下輸入String型別,會怎麼樣?
很明顯,直接就報錯了
這樣就更好的利用了程式碼的複用性。上面部分的知識點也就是泛型類。
我們先定義一個泛型父類別:()
public class Student<T> { private T t; public T getT() {return t;} public void setT(T t) {this.t = t;} }
然後定義一個子類,繼承該Student父類別:
public class Child<T> extends Student<T>{ @Override public T getT(){ return super.getT(); } @Override public void setT(T t){ super.setT(t); } }
特別需要注意:
1.泛型子類的引數一定要和父類別的引數型別一致
2.如果子類沒有新增泛型,那麼父類別的引數型別必須明確
也就是這樣:
public class Child extends Student<Integer>{ }
測試:下面程式碼的解釋:在父類別Student內定義泛型為String,然後建立子類Child的物件child,因為是繼承關係,所有child的泛型也是String,
public class Test { public static void main(String[] args) { Student<String> child = new Child<>(); //多型 child.setT("abc"); String value = child.getT(); System.out.println(value); } }
當子類傳入非String型別值時:
泛型介面其實也很簡單,定義如下:
public interface USB<T> { }
泛型子類實現泛型介面,除了處理標識父類別的泛型標識外,還可以繼續擴充套件泛型:
public class phone<T,V> implements USB<T>{ //這裡的意思是子類除了有USB介面的泛型T類,也可以再擴充套件一個泛型 private T color; //手機顏色 private V phoneName; //手機名稱 public phone(T color,V phoneName) { this.color = color; this.phoneName = phoneName; } public T getColor() { return color; } public void setColor(T color) { this.color = color; } public V getPhoneName() { return phoneName; } public void setPhoneName(V phoneName) { this.phoneName = phoneName; } }
注意: 泛型介面也和泛型父子類一樣,如果子類沒有新增泛型引數,那麼父類別一定要明確的指定型別!
public class phone implements USB<String>{ }
測試:
分別把T和V的泛型都定義為String:
public class Test { public static void main(String[] args) { phone<String,String> ph = new phone<>("黑色","華為"); String str1 = ph.getColor(); String str2 = ph.getPhoneName(); System.out.println(str1+str2); } }
定義泛型方法:在public和返回值之間定義<>的才是泛型方法:
public<E> void printType(){ }
然而這個方法的返回值型別就是取決於E的型別,如果E是Integer,那麼這個方法的返回值型別就是整數。用法基本和上述的一致,需要什麼型別的返回值,在呼叫的時候去傳遞泛型型別即可。
萬用字元一般是使用 ? 代替具體的型別實參(此處是型別實參,而不是型別形參)。當操作型別時不需要使用型別的具體功能時,只使用Object類中的功能,那麼可以用 ? 萬用字元來表未知型別。例如 List<?> 在邏輯上是List、List 、List等所有List<具體型別實參>的父類別。
有界的型別引數:
有的時候需要限制那些被允許傳遞到一個型別引數的型別種類範圍,例如一個運算元字的方法可能只希望接受Number或者Number子類的範例。這時就需要為泛型新增上邊界,即傳入的型別實參必須是指定型別的子型別。要宣告一個有界的型別引數,首先列出型別引數的名稱,後跟extends或super關鍵字,最後緊跟它的上界或下界。由此可以知道泛型的上下邊界的新增必須與泛型的宣告在一起 。
上限: <? extends T>:
表示該萬用字元所代表的型別是T型別的子類。 例如往集合中新增元素時,既可以新增T型別物件,又可以新增T的子型別物件。
下限:<? super T>:
表示該萬用字元所代表的型別是T型別的父類別,就是隻能獲取到T類及以上的泛型,任何繼承T類的泛型將得不到。
建一個動物的父類別:
public class Animal { }
建一個貓類,繼承父類別:
public class Cat extends Animal{ }
建一個小貓類,繼承貓類:
public class MiniCat extends Cat{ }
現在的關係是Animal>Cat>MiniCat
萬用字元上限的測試類:
public class test { public static void main(String[] args) { ArrayList<Animal> animals = new ArrayList<>(); ArrayList<Cat> cats = new ArrayList<>(); ArrayList<MiniCat> minicats = new ArrayList<>(); showAnimals(cats); showAnimals(minicats); //這樣會報錯,因為在showAnimals方法內的萬用字元最高繼承自Cat showAnimals(animals); } //使用萬用字元,把上線限制到Cat,意思是Animal這個類不能被獲取 private static void showAnimals(ArrayList<? extends Cat> cats) { for (Cat cat:cats ) { System.out.println(cat); } } }
可以看到使用萬用字元限制到Cat類後,Animals這個類就已經獲取不到了。這就是上限。
如果把上限設定成Animal的時候:
萬用字元下限的測試類:(其他程式碼與上面的一致)
public class test { public static void main(String[] args) { ArrayList<Animal> animals = new ArrayList<>(); ArrayList<Cat> cats = new ArrayList<>(); ArrayList<MiniCat> minicats = new ArrayList<>(); showAnimals(cats); showAnimals(minicats); //這樣會報錯,因為在showAnimals方法內的萬用字元最高繼承自Cat showAnimals(animals); } //使用萬用字元,把上線限制到Cat,意思是Animal這個類不能被獲取 private static void showAnimals(ArrayList<? extends Cat> cats) { for (Cat cat:cats ) { System.out.println(cat); } } }
因為萬用字元設定了下限到Cat類,所以MiniCat是獲取不到的:
以上就是關於泛型和萬用字元的介紹,泛型可以在類、介面、方法中使用,分別簡稱之泛型類、泛型介面、泛型方法,並且通過泛型實現資料型別的任意化,即靈活、又有安全性,易於維護。在編譯過中,對於正確檢驗泛型結果後,會將泛型的相關資訊擦出,也就是說,成功編譯過後的class檔案中是不包含任何泛型資訊的。泛型資訊不會進入到執行時階段。
總而言之,泛型是在編譯的時候檢查型別安全,所有的強制轉換都是自動和隱式的,提高程式碼的重用率。並且消除強制型別轉換,在傳入引數的時候就已經限制的型別。
本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注it145.com的更多內容!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45