国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

深入理解java泛型Generic

發(fā)布時(shí)間:2021-07-06 11:13 來(lái)源:腳本之家 閱讀:0 作者:chengyu0726 欄目: 開(kāi)發(fā)技術(shù)

目錄

                一、背景

                泛型技術(shù)誕生之前(JDK5以前),創(chuàng )建集合的類(lèi)型都是Object 類(lèi)型的元素,存儲內容沒(méi)有限制,編譯時(shí)正常,運行時(shí)容易出現ClassCastException 異常。

                public class Test {
                	public static void main(String[] args) {
                		ArrayList list = new ArrayList();
                		list.add("java");
                		list.add(100);
                		list.add(true);
                		for(int i = 0;i <list.size();i++) {
                			Object o = list.get(i);
                			String str = (String)o;
                			System.out.println(str);
                		}
                	}
                }
                

                輸出:

                java
                Exception in thread “main” java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
                at com.chengyu.junit.Test.main(Test.java:18)

                二、泛型概念

                JDK5 中引入泛型,從而可以在編譯時(shí)檢測是否存在非法的類(lèi)型數據結構。
                其本質(zhì)就是參數化類(lèi)型,可以用于類(lèi)、接口和方法中,分別被稱(chēng)為泛型類(lèi)、泛型接口、泛型方法。

                public static void main(String[] args) {
                		ArrayList<String> strList = new ArrayList<String>();
                		strList.add("java");
                		strList.add("C#");
                
                		for(int i = 0;i < strList.size();i++) {
                			String str = strList.get(i);
                			System.out.println(str);
                		}
                	}
                

                三、泛型類(lèi)

                3.1 定義與調用

                定義類(lèi)時(shí)設置泛型,該泛型可用于類(lèi)中的屬性或方法中,調用該泛型類(lèi)時(shí),指定具體類(lèi)型;

                // 調用泛型類(lèi)
                public class GenericTest {
                	public static void main(String[] args) {
                		Generic<String> strGen = new Generic<>("a");
                		String key = strGen.getKey();
                		System.out.println(key);
                	}
                }
                // 定義泛型類(lèi)
                // @param <T> 使用類(lèi)時(shí)指定
                class Generic<T>{
                	private T key;
                	public Generic(T key) {
                		this.key = key;
                	}
                	public T getKey() {
                		return key;
                	}
                	public void setKey(T key) {
                		this.key = key;
                	}
                	@Override
                	public String toString() {
                		return "GenericTest [key=" + key + "]";
                	}
                }
                

                3.2 注意

                1)調用泛型類(lèi)時(shí)未定義類(lèi)型,則會(huì )按照Object 類(lèi)型處理;
                2)調用時(shí)分別指定不同類(lèi)型,但本質(zhì)都是Object 類(lèi)型;
                3)泛型不支持基本數據類(lèi)型;
                4)泛型類(lèi)的成員方法不可以用static 修飾(泛型方法可以)。

                3.3 使用

                需求:抽獎活動(dòng),但抽獎內容沒(méi)有確定,可能都是現金,也可能都是物品

                public class ProductGetterTest {
                	public static void main(String[] args) {
                		// 抽物品
                		ProductGetter<String> strProductGetter = new ProductGetter<>();
                		String[] str = {"手機","電視","洗衣機"};
                		for(int i = 0; i < str.length; i ++ ) {
                			strProductGetter.addProduct(str[i]);
                		}
                		String strProduct = strProductGetter.getProduct();
                		System.out.println("恭喜您抽中了" + strProduct);
                
                		System.out.println("=============================================");
                		// 抽現金
                		ProductGetter<Integer> intProductGetter = new ProductGetter<>();
                		Integer[] integer = {1000,2000,3000};
                		for(int i = 0; i < integer.length; i ++ ) {
                			intProductGetter.addProduct(integer[i]);
                		}
                		int intProduct = intProductGetter.getProduct();
                		System.out.println("恭喜您抽中了" + intProduct);
                	}
                }
                // 抽獎器
                class ProductGetter<T>{
                	Random random = new Random();
                	// 獎品池
                	ArrayList<T> list = new ArrayList<>();
                	// 添加獎品
                	public void addProduct(T t) {
                		list.add(t);
                	}
                	// 抽獎(獲取獎品)
                	public T getProduct() {
                		 return list.get(random.nextInt(list.size()));
                	}
                }
                

                3.4 泛型類(lèi)的繼承

                3.4.1 子類(lèi)也是泛型類(lèi)

                子類(lèi)也是泛型類(lèi),則泛型要保持一致。

                class ChildFirst<T> extends Parent{ ... }

                1)指定子類(lèi)泛型,不指定父類(lèi)泛型,父類(lèi)默認為Object 類(lèi)型

                class Parent<E>{
                	private E value;
                	public E getValue() {
                		return value;
                	}
                	public void setValue(E value) {
                		this.value = value;
                	}
                }
                class ChildFirst<T> extends Parent{
                	@Override
                	public Object getValue() {
                		return super.getValue();
                	}
                }
                

                2)若父類(lèi)保留原有泛型,與子類(lèi)泛型不一致,則會(huì )編譯出錯

                class ChildFirst<T> extends Parent<E>{
                	@Override
                	public E getValue() {
                		return super.getValue(); 
                	}

                3)父類(lèi)泛型與子類(lèi)保持一致
                具體泛型指定是由子類(lèi)傳遞到父類(lèi)當中,所以繼承時(shí)父類(lèi)要與子類(lèi)泛型保持一致(當然都寫(xiě)成E也可以)。

                class Parent<E>{
                	private E value;
                	public E getValue() {
                		return value;
                	}
                	public void setValue(E value) {
                		this.value = value;
                	}
                }
                class ChildFirst<T> extends Parent<T>{
                	@Override
                	public T getValue() {
                		return super.getValue();
                	}
                }
                

                4)調用

                public class GenericTest {
                	public static void main(String[] args) {
                		ChildFirst<String> childFirst = new ChildFirst<>();
                		childFirst.setValue("chengyu");
                		System.out.println(childFirst.getValue());
                	}
                }
                

                5)補充:
                子類(lèi)可以進(jìn)行泛型擴展,但子類(lèi)必須有一個(gè)泛型與父類(lèi)一致

                public class GenericTest {
                	public static void main(String[] args) {
                		ChildFirst<String,Integer> childFirst = new ChildFirst<>();
                		childFirst.setValue("chengyu");
                		System.out.println(childFirst.getValue());
                	}
                }
                class Parent<E>{
                	private E value;
                	public E getValue() {
                		return value;
                	}
                	public void setValue(E value) {
                		this.value = value;
                	}
                }
                class ChildFirst<T,E> extends Parent<T>{
                	@Override
                	public T getValue() {
                		return super.getValue();
                	}
                }
                

                3.4.2 子類(lèi)不是泛型類(lèi)

                子類(lèi)不是泛型類(lèi),父類(lèi)要明確泛型的數據類(lèi)型

                class ChildSecond extends Parent<String>{ ... }

                1)子類(lèi)不是泛型類(lèi),不指定父類(lèi)泛型,父類(lèi)默認為Object 類(lèi)型

                class Parent<E>{
                	private E value;
                	public E getValue() {
                		return value;
                	}
                	public void setValue(E value) {
                		this.value = value;
                	}
                }
                class ChildSecond extends Parent{
                	@Override
                	public Object getValue() {
                		return super.getValue();
                	}
                }
                

                2)父類(lèi)要明確泛型的數據類(lèi)型

                class ChildSecond extends Parent<String>{
                	@Override
                	public String getValue() {
                		return super.getValue();
                	}
                }

                3)調用

                public class GenericTest {
                	public static void main(String[] args) {
                		ChildSecond childSecond = new ChildSecond();
                		childSecond.setValue("chengyu2");
                		System.out.println(childSecond.getValue());
                	}
                }
                

                四、泛型接口

                4.1 定義

                public interface Generator<T>{ ... }

                4.2 使用(與繼承特點(diǎn)相同)

                4.2.1 實(shí)現類(lèi)不是泛型類(lèi)

                實(shí)現類(lèi)不是泛型類(lèi),接口要明確數據類(lèi)型

                class Apple implements Generator<String>{
                	@Override
                	public String getKey() {
                		return "Generator interface";
                	}
                }

                4.2.2 實(shí)現類(lèi)也是泛型類(lèi)

                實(shí)現類(lèi)也是泛型類(lèi),實(shí)現類(lèi)和接口的泛型類(lèi)型要一致

                class Apple<T> implements Generator<T>{
                	private T key;
                	@Override
                	public T getKey() {
                		return key;
                	}
                }

                五、泛型方法

                5.1 定義

                5.1.1 泛型方法

                修飾符 <T,E,..> 返回值類(lèi)型 方法名(形參列表){
                }
                
                // 泛型方法
                public <E,T> E getProduct(ArrayList<E> list) {
                	return list.get(random.nextInt(list.size()));
                }

                5.1.2 靜態(tài)泛型方法

                修飾符 <T,E,..> 返回值類(lèi)型 方法名(形參列表){
                }
                
                // 泛型方法
                public <E,T> E getProduct(ArrayList<E> list) {
                	return list.get(random.nextInt(list.size()));
                }

                5.1.3 可變參數的泛型方法

                public <E> void print(E... e) {
                	for(int i = 0; i < e.length;i++){
                		System.out.println(e[i]);
                	}
                }
                // 調用
                print(1,2,3,4);

                5.2 注意

                1)包含泛型列表的方法才是泛型方法,泛型類(lèi)中使用了泛型的方法并不是泛型方法;
                2)泛型列表中聲明了泛型類(lèi)型,才可以在方法中使用泛型類(lèi)型;
                3)泛型方法中的泛型類(lèi)型獨立于泛型類(lèi)的泛型,與類(lèi)泛型類(lèi)型無(wú)關(guān);
                4)泛型方法可以用static 修飾(泛型類(lèi)的成員方法不可以)。

                5.3 使用

                5.3.1 定義泛型方法

                // 抽獎器
                // @param <t>
                class ProductGetter<T>{
                	Random random = new Random();
                	// 獎品池
                	ArrayList<T> list = new ArrayList<>();
                	// 添加獎品
                	public void addProduct(T t) {
                		list.add(t);
                	}
                	// 抽獎(獲取獎品)
                	public T getProduct() {
                		 return list.get(random.nextInt(list.size()));
                	}
                	// 泛型方法
                	public <E> E getProduct(ArrayList<E> list) {
                		return list.get(random.nextInt(list.size()));
                	}
                }
                

                5.3.2 調用泛型方法

                public class ProductGetterTest {
                	public static void main(String[] args) {
                		ProductGetter<Integer> intProductGetter = new ProductGetter<>();
                
                		ArrayList<String> strList = new ArrayList<>();
                		strList.add("手機");
                		strList.add("電視");
                		strList.add("洗衣機");
                
                		String product = intProductGetter.getProduct(strList);
                		System.out.println("恭喜您抽中了" + product);
                	}
                }
                

                六、類(lèi)型通配符

                6.1 類(lèi)型通配符介紹

                類(lèi)型通配符一般用【?】代替具體的類(lèi)型 實(shí)參;

                6.2 為什么要用類(lèi)型通配符

                泛型類(lèi)被調用時(shí),需要指定泛型類(lèi)型,當泛型類(lèi)的方法被調用時(shí),不能靈活對應多種泛型類(lèi)型的需求,如下面代碼部分所示:

                public class BoxTest {
                	public static void main(String[] args) {
                		// 3.調用showBox
                		Box<Number> box1 = new Box<>();
                		box1.setFirst(100);
                		showBox(box1);
                		// 4.再次調用showBox
                		// 出現問(wèn)題:類(lèi)型發(fā)生變化后會(huì )報錯
                		Box<Integer> box2 = new Box<>();
                		box2.setFirst(200);
                		showBox(box2);
                	}
                	// 2. 調用泛型類(lèi),此時(shí)需要指定泛型類(lèi)型
                	public static void showBox(Box<Number> box) {
                		Number first = box.getFirst();
                		System.out.println(first);
                	}
                }
                // 1.定義泛型類(lèi)
                class Box<E>{
                	private E first;
                	public E getFirst() {
                		return first;
                	}
                	public void setFirst(E first) {
                		this.first = first;
                	}
                }
                

                解決上述問(wèn)題,類(lèi)型通配符【?】登場(chǎng)

                public class BoxTest {
                	public static void main(String[] args) {
                		// 3.調用showBox
                		Box<Number> box1 = new Box<>();
                		box1.setFirst(100);
                		showBox(box1);
                		// 4.再次調用showBox
                		// 問(wèn)題得以解決
                		Box<Integer> box2 = new Box<>();
                		box2.setFirst(200);
                		showBox(box2);
                	}
                	// 2. 調用泛型類(lèi),此時(shí)需要指定泛型類(lèi)型
                	// 【?】類(lèi)型通配符等成
                	public static void showBox(Box<?> box) {
                		Object first = box.getFirst();
                		System.out.println(first);
                	}
                }
                // 1.定義泛型類(lèi)
                class Box<E>{
                	private E first;
                	public E getFirst() {
                		return first;
                	}
                	public void setFirst(E first) {
                		this.first = first;
                	}
                }
                

                6.3 泛型通配符上限 extends

                【6.2】代碼例中,雖然使用了通配符,但 box.getFirst()返回類(lèi)型仍然需要定義成Object 類(lèi)型,并不理想。

                public static void showBox(Box<?> box) {
                	Object first = box.getFirst();
                	System.out.println(first);
                }

                通配符上限登場(chǎng):
                調用showBox 方法時(shí),傳遞的泛型類(lèi)型可以是Number 及其子類(lèi)(Integer)

                public static void showBox(Box<? extends Number> box) {
                	Number first = box.getFirst();
                	System.out.println(first);
                }

                注意:

                public static void showBox(Box<? extends Number> box) {
                	Number first = box.getFirst();
                	// 此處編譯報錯:類(lèi)型不一致
                	// 雖然定義上限,showBox 被調用時(shí)沒(méi)問(wèn)題,但在方法內同時(shí)定義多種類(lèi)型,編譯器無(wú)法識別
                	Integer second = box.getFirst();
                	System.out.println(first);
                }
                

                6.4 泛型通配符下限 super

                public static void showBox(Box<? super Integer> box) {
                	Number first = box.getFirst();
                	System.out.println(first);
                }

                注意:
                遍歷時(shí)要用Object 類(lèi)型進(jìn)行遍歷;

                七、類(lèi)型擦除

                泛型信息只存在于代碼編譯階段,進(jìn)入JVM之前,與泛型相關(guān)的信息會(huì )被擦除,這個(gè)行為稱(chēng)為類(lèi)型擦除。

                到此這篇關(guān)于深入理解java泛型Generic的文章就介紹到這了,更多相關(guān)java泛型內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

                免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。

                67194熟妇人妻欧美日韩| 影音最新资源在线观看| 美女无遮挡免费视频网站| 忍着娇喘人妻被中出中文字幕| 国产果冻豆传媒麻婆精东| 无码囯产精品一区二区免费|