首頁  >  文章  >  Java  >  Java中泛型的型別屏蔽特性對程式碼有何影響?

Java中泛型的型別屏蔽特性對程式碼有何影響?

WBOY
WBOY轉載
2023-04-26 13:34:081251瀏覽

使用泛型屏蔽類型的差異性

在C 語言中,有個很好用的模板(template)功能,可以編寫帶有參數化類型的通用版本,讓編譯器自動生成針對不同類型的具體版本。而在Java語言中,也有一個類似的功能叫泛型(generic)。在寫類別和方法的時候,一般使用的是具體的類型,而用泛型可以讓類型參數化,這樣就可以寫出更通用的程式碼。

許多人都認為,C 模板(template)和Java泛型(generic)兩個概念是等價的,其實實作機制是完全不同的。 C 模板是一套巨集指令集,編譯器會針對每種類型建立一份模板程式碼副本;Java泛型的實作是基於"型別擦除"概念,本質上是一種進行型別限制的語法糖。

1.泛型類別

以支撐類別為例,定義泛型的通用支撐類別:

/** 通用支撑类 */@Getter@Setter@ToStringpublic class GenericHolder<T> {    /** 通用取值 */
    private T value;    /** 构造函数 */
    public GenericHolder() {}    /** 构造函数 */
    public GenericHolder(T value) {        this.value = value;
    }
}

2.泛型介面

定義泛型的資料提供者介面:

/** 数据提供者接口 */public interface DataProvider<T> {    /** 获取数据函数 */
    public T getData();
}

3.泛型方法

定義泛型的淺拷貝函數:

/** 浅拷贝函数 */public static <T> T shallowCopy(Object source, Class<T> clazz) throws BeansException {    // 判断源对象
    if (Objects.isNull(source)) {        return null;
    }    // 新建目标对象
    T target;    try {
        target = clazz.newInstance();
    } catch (Exception e) {        throw new BeansException("新建类实例异常", e);
    }    // 拷贝对象属性
    BeanUtils.copyProperties(source, target);    // 返回目标对象
    return target;
}

4.泛型通配符

#泛型通配符一般是使用"?"代替具體的類型實參,可以把"?"看成所有類型的父類。當具體類型不確定的時候,可以使用泛型通配符 "?";當不需要使用類型的特定功能,只使用Object類別中的功能時,可以使用泛型通配符 "?"。

/** 打印取值函数 */public static void printValue(GenericHolder<?> holder) {
    System.out.println(holder.getValue());
}/** 主函数 */public static void main(String[] args) {
    printValue(new GenericHolder<>(12345));
    printValue(new GenericHolder<>("abcde"));
}

在Java規格中,不建議使用泛型通配符"?",上面函數可以改為:

/** 打印取值函数 */public static <T> void printValue(GenericHolder<T> holder) {
    System.out.println(holder.getValue());
}

5.泛型上下界

在使用泛型的時候,我們還可以為傳入的泛型類型實參進行上下界的限制,如:類型實參只準傳入某種類型的父類或某種類型的子類。泛型上下界的聲明,必須與泛型的聲明放在一起 。

上界通配符(extends):

上界通配符為”extends”,可以接受其指定型別或其子類作為泛參。其還有一種特殊的形式,可以指定其不僅要是指定類型的子類,還要實作某些介面。例如:List表示這是A某個特定子類別的List,保存的物件必須是A或A的子類別。對於List列表,不能新增A或A的子類別對象,只能取得A的對象。

下界通配符(super):

下界通配符為”super”,可以接受其指定型別或其父類作為泛參。例如:List表示這是A某個具體父類別的List,保存的物件必須是A或A的超類別。對於List列表,能夠新增A或A的子類別對象,但只能取得Object的物件。

PECS(Producer Extends Consumer Super)原則:
作為生產者提供資料(往外讀取)時,適合用上界通配符(extends);
作為消費者消費資料(往裡寫入)時,適合用下界通配符(super)。

在日常編碼中,比較常用的是上界通配符(extends),用來限定泛型類型的父類別。範例程式碼如下:

/** 数字支撑类 */@Getter@Setter@ToStringpublic class NumberHolder<T extends Number> {    /** 通用取值 */
    private T value;    /** 构造函数 */
    public NumberHolder() {}    /** 构造函数 */
    public NumberHolder(T value) {        this.value = value;
    }
}/** 打印取值函数 */public static <T extends Number> void printValue(GenericHolder<T> holder) {
    System.out.println(holder.getValue());
}

以上是Java中泛型的型別屏蔽特性對程式碼有何影響?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除