国产另类ts人妖一区二区_欧美肥老太做爰视频_快穿高h肉_国产欧美综合在线

當前位置: 首頁 / 技術干貨 / 正文
民哥帶你快速精通java泛型(五)

2022-10-24

泛型 類型 定義

  第五關 泛型的離奇失蹤

  小伙們看到這個標題,可能會大吃一驚,我們不是定義好泛型了嗎,那么泛型還會突然離奇失蹤啊。

  我可以很負責的告訴小伙們: 泛型確實會消失!

  1. 泛型的擦除機制(泛型消失)

好程序員

  我們定義的泛型類,泛型方法,只是編譯時:規范類型參數的傳遞,然而在編譯成class文件后,運行代碼時,這時泛型就消失了。

  原因就是:

  在JAVA的虛擬機中并不存在泛型,泛型只是為了完善java體系,增加程序員編程的便捷性以及安全性而創建的一種機制,在JAVA虛擬機中對應泛型的都是確定的類型,在編寫泛型代碼后,java虛擬機中會把這些泛型參數類型都擦除,用相應的確定類型來代替,代替的這一動作叫做類型擦除,而用于替代的類型稱為原始類型,在類型擦除過程中,一般使用第一個限定的類型來替換,若無限定,則使用Object.

  下面我們測試一下:

  //1.在Demo.java類中: 定義一個泛型的集合

  Listlist = new ArrayList();

  list.add("hello");

  list.add("java");

  //2.在編譯后的Demo.class文件中,通過反編譯查看:泛型消失了

  List list = new ArrayList();

  list.add("hello");

  list.add("java");

  2.泛型的擦除補償

  正如我們看到的,我們在代碼運行時,泛型就消失了,那么如果我們在運行代碼時需要確切的知道泛型的具體類型該怎么辦呢?特別是使用new T(),或者使用instanceof, 因為這兩類操作要知道確切的類型。

  我們可以通過泛型擦除后的補償來滿足我們的需求,一般我們會采用java中的設計模式來解決這個問題。

  方式一:簡單工廠 (最簡單)

  在此方法中,將類型作為參數,以一個萬能的工廠類(其中有一個返回具體類型類的實例的泛型方法)用類的

  newInstance()方法返回參數化類型的實例,如下所示:

/**
* 定義泛型T
* @param <T>
*/
public class GenericDemo9<T> {
//1.定義泛型變量: t
private T t;
//2.定義方法:獲取t
public T getInstance(Class<T> clz){
try {
this.t = clz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return this.t;
}
//3.測試:
public static void main(String[] args) {
GenericDemo9<Date> gd = new GenericDemo9<Date>();
Date date = gd.getInstance(Date.class);
}

}

  缺點:

  因為class的newInstance()是利用無參構造方法創建對象的,如果該泛型類沒有無參構造方法,就會報錯

  方式二:工廠方法(最靈活)

  與簡單工廠相比,工廠方法更靈活,同時來解決了簡單工廠中沒有無參構造方法,不能創建對象的問題。

  如下所示:

//步驟一: 定義工廠接口
/**
* 定義一個泛型接口
* @param <T>
*/
public interface GenericFactory<T> {
T create();
}
//步驟二:定義具體創建對象的工廠
/**
* 定義生產汽車的工廠
*/
class CarFactory implements GenericFactory<Car>{
//1.定義汽車的名稱
private String name;
//2. 定義汽車對象
private Car car;

public CarFactory() {
}

public CarFactory(String name) {
this.name = name;
}

@Override
public Car create() {
if(name==null){//沒有汽車名稱:表示使用無參數構造
this.car = new Car();
}else{//有汽車名稱:表示使用有參數構造
this.car = new Car(this.name);
}
return car;
}
//3.測試
public static void main(String[] args) {
GenericFactory<Car> gf = new CarFactory();
Car car = gf.create();//使用無參構造創建對象
GenericFactory<Car> gf2 = new CarFactory("奔馳S500");
Car car2 = gf2.create();//使用有參構造創建對象

}
}
//步驟三:定義對象的類
//定義一個汽車類
class Car{
private String name;
public Car() {
}
public Car(String name) {
this.name = name;
}
}

  缺點:代碼實現起來麻煩

  優點:創建對象的方式更加靈活,使用有參和無參構造都能創建對象。

  模板方法(最簡捷)與工廠方法不同的地方在于:用模板類(抽象類)來控制整個實例化過程的流程,本質就是用模板類控制對象的創建過程,具體創建對象的實現由模板類的子類去實現,只不過在模板類中需要用工廠方法。

  如下所示:

//1.創建模板類
public abstract class GenericTemplate<T> {
//1.定義泛型變量
private T t;
//2.定義抽象方法
public abstract T create();
}
//2.創建模板類的生成者(實現類)
class CarCreator extends GenericTemplate<Car> {
//1.定義工廠對象:引入工廠方法
private CarFactory cf ;

public CarCreator() {
this.cf = new CarFactory();
}

public CarCreator(String carName) {
this.cf = new CarFactory(carName);
}
//2.重寫模板類的方法
@Override
public Car create() {
return cf.create();
}
}

  優點:

  方式最簡捷,因為直接調用具體的生成類即可,我們創建對象時,并看不到模板類的出現。

  闖關練習

  請描述 代碼在運行過程中 泛型在擦除后,具體表示為什么類型?(單選)

  A: Class類型

  B: T類型

  C: Object類型

  D: Type類型

  答案:C

  解析:

  在代碼運行過程中,泛型會被擦除(也就是泛型會消失),這時泛型的類型通通都會表示為Object類型。

  因為定義泛型時,可以指定任意類型,比如List<String>,Set<Number>,所以在泛型擦除后,只有Object類型可以表示任意類型。

好程序員公眾號

  • · 剖析行業發展趨勢
  • · 匯聚企業項目源碼

好程序員開班動態

More+
  • HTML5大前端 <高端班>

    開班時間:2021-04-12(深圳)

    開班盛況

    開班時間:2021-05-17(北京)

    開班盛況
  • 大數據+人工智能 <高端班>

    開班時間:2021-03-22(杭州)

    開班盛況

    開班時間:2021-04-26(北京)

    開班盛況
  • JavaEE分布式開發 <高端班>

    開班時間:2021-05-10(北京)

    開班盛況

    開班時間:2021-02-22(北京)

    開班盛況
  • Python人工智能+數據分析 <高端班>

    開班時間:2021-07-12(北京)

    預約報名

    開班時間:2020-09-21(上海)

    開班盛況
  • 云計算開發 <高端班>

    開班時間:2021-07-12(北京)

    預約報名

    開班時間:2019-07-22(北京)

    開班盛況
IT培訓IT培訓
在線咨詢
IT培訓IT培訓
試聽
IT培訓IT培訓
入學教程
IT培訓IT培訓
立即報名
IT培訓

Copyright 2011-2023 北京千鋒互聯科技有限公司 .All Right 京ICP備12003911號-5 京公網安備 11010802035720號