亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java中泛型Generic的作用是什么

發布時間:2021-05-12 16:29:43 來源:億速云 閱讀:192 作者:Leah 欄目:開發技術

java中泛型Generic的作用是什么?針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

1. 背景

泛型技術誕生之前(JDK5以前),創建集合的類型都是Object 類型的元素,存儲內容沒有限制,編譯時正常,運行時容易出現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)

2. 泛型概念

JDK5 中引入泛型,從而可以在編譯時檢測是否存在非法的類型數據結構
其本質就是參數化類型,可以用于類、接口和方法中,分別被稱為泛型類、泛型接口、泛型方法

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);
		}
	}

3. 泛型類

3.1 定義與調用

定義類時設置泛型,該泛型可用于類中的屬性或方法中,調用該泛型類時,指定具體類型;

// 調用泛型類
public class GenericTest {
	public static void main(String[] args) {
		Generic<String> strGen = new Generic<>("a");
		String key = strGen.getKey();
		System.out.println(key);
	}
}
// 定義泛型類
// @param <T> 使用類時指定
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)調用泛型類時未定義類型,則會按照Object 類型處理;
2)調用時分別指定不同類型,但本質都是Object 類型;
3)泛型不支持基本數據類型;
4)泛型類的成員方法不可以用static 修飾(泛型方法可以)。

3.3 使用

需求:抽獎活動,但抽獎內容沒有確定,可能都是現金,也可能都是物品

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 泛型類的繼承

3.4.1 子類也是泛型類

子類也是泛型類,則泛型要保持一致。

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

1)指定子類泛型,不指定父類泛型,父類默認為Object 類型

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)若父類保留原有泛型,與子類泛型不一致,則會編譯出錯

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

3)父類泛型與子類保持一致
具體泛型指定是由子類傳遞到父類當中,所以繼承時父類要與子類泛型保持一致(當然都寫成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)補充:
子類可以進行泛型擴展,但子類必須有一個泛型與父類一致

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 子類不是泛型類

子類不是泛型類,父類要明確泛型的數據類型

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

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

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)父類要明確泛型的數據類型

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. 泛型接口

4.1 定義

public interface Generator<T>{ ... }

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

4.2.1 實現類不是泛型類

實現類不是泛型類,接口要明確數據類型

class Apple implements Generator<String>{
	@Override
	public String getKey() {
		return "Generator interface";
	}
}
4.2.2 實現類也是泛型類

實現類也是泛型類,實現類和接口的泛型類型要一致

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

5. 泛型方法

5.1 定義

5.1.1 泛型方法
修飾符 <T,E,..> 返回值類型 方法名(形參列表){
}

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

// 泛型方法
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)包含泛型列表的方法才是泛型方法,泛型類中使用了泛型的方法并不是泛型方法;
2)泛型列表中聲明了泛型類型,才可以在方法中使用泛型類型;
3)泛型方法中的泛型類型獨立于泛型類的泛型,與類泛型類型無關;
4)泛型方法可以用static 修飾(泛型類的成員方法不可以)。

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);
	}
}

6. 類型通配符

6.1 類型通配符介紹

類型通配符一般用【?】代替具體的類型 實參

6.2 為什么要用類型通配符

泛型類被調用時,需要指定泛型類型,當泛型類的方法被調用時,不能靈活對應多種泛型類型的需求,如下面代碼【4.】部分所示:

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

解決上述問題,類型通配符【?】登場

public class BoxTest {
	public static void main(String[] args) {
		// 3.調用showBox
		Box<Number> box1 = new Box<>();
		box1.setFirst(100);
		showBox(box1);
		// 4.再次調用showBox
		// 問題得以解決
		Box<Integer> box2 = new Box<>();
		box2.setFirst(200);
		showBox(box2);
	}
	// 2. 調用泛型類,此時需要指定泛型類型
	// 【?】類型通配符等成
	public static void showBox(Box<?> box) {
		Object first = box.getFirst();
		System.out.println(first);
	}
}
// 1.定義泛型類
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()返回類型仍然需要定義成Object 類型,并不理想。

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

通配符上限登場:
調用showBox 方法時,傳遞的泛型類型可以是Number 及其子類(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();
	// 此處編譯報錯:類型不一致
	// 雖然定義上限,showBox 被調用時沒問題,但在方法內同時定義多種類型,編譯器無法識別
	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);
}

注意:
遍歷時要用Object 類型進行遍歷;

7. 類型擦除

泛型信息只存在于代碼編譯階段,進入JVM之前,與泛型相關的信息會被擦除,這個行為稱為類型擦除。

Java有哪些集合類

Java中的集合主要分為四類:1、List列表:有序的,可重復的;2、Queue隊列:有序,可重復的;3、Set集合:不可重復;4、Map映射:無序,鍵唯一,值不唯一。

關于java中泛型Generic的作用是什么問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

杭州市| 霍林郭勒市| 新竹市| 茶陵县| 民乐县| 应城市| 科技| 舞阳县| 盖州市| 策勒县| 安阳县| 寿阳县| 沙洋县| 陆河县| 盐城市| 汕头市| 曲松县| 阳曲县| 山东省| 万宁市| 衡东县| 绍兴县| 临沭县| 集贤县| 乌拉特前旗| 左权县| 平定县| 德钦县| 镇坪县| 商河县| 方山县| 措美县| 乐安县| 南通市| 特克斯县| 隆子县| 兴国县| 麦盖提县| 石台县| 西藏| 高密市|