国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java泛型

lauren_liuling / 3066人閱讀

摘要:通過方法返回值來確定具體泛型類型。泛型類定義的泛型聲明在整個類定義中都有效。相同類型參數(shù)的泛型類的關(guān)系取決于泛型類自身的繼承體系結(jié)構(gòu)。

首先,明確一點的是:java的泛型是擦除的。
即系,泛型只存在于編譯時,編譯后都是Object類型(也不全是,見后面解析,運行時也能獲得一定的泛型信息)。

泛型對于Java編程的作用:

最主要:增加編譯時的類型安全檢查。
其次:你說它能做到抽取不同類型的共同代碼的話,可能就只適用于容器類。容器類中適合存放不同的類型,而且不管存放的類型是什么都適用。但是要求存放的類型是要一致。

泛型的所做的實質(zhì)工作:
編譯時,在泛型類的入口(如:方法參數(shù)),會進(jìn)行編譯時的類型安全檢查(子類,父類關(guān)系檢查,是否是安全的向上轉(zhuǎn)型)。
而且編譯器會在編譯時增加語法糖,對泛型類的出口(如: 返回值),編譯器會對字節(jié)碼自動增加類型轉(zhuǎn)換的代碼。

編譯前的泛型類:

public static void main(String[] args) {
    Map map = new HashMap();
    map.put("hello", "你好");
    map.put("how are you?", "吃了沒?");
    System.out.println(map.get("hello"));
    System.out.println(map.get("how are you?"));
}

把上面的代碼編譯成class文件后,再用字節(jié)碼反編譯工具進(jìn)行反編譯后:

public static void main(String[] args) {
    Map map = new HashMap();
    map.put("hello", "你好");
    map.put("how are you?", "吃了沒?");
    System.out.println((String) map.get("hello"));
    System.out.println((String) map.get("how are you?"));
}

在運行時,
(重要!)總結(jié):擦除法所謂的擦除,僅僅是對字節(jié)碼中方法中的方法體的Code屬性中的字節(jié)碼進(jìn)行擦除(即方法體中的代碼沒有泛型),但是實際上的元數(shù)據(jù)(類定義,方法定義,字段定義)的Signature中還是保存著 具體參數(shù)化類型 信息。
上面描述的具體參數(shù)化類型信息,可以供用戶查詢得到。
(如:類定義MyList implements List 中, 在MyList字節(jié)碼的類定義中會保存 具體參數(shù)化類型信息----(String) )。

在編譯時,
我們知道編譯器時掌握泛型信息的。
那么問題剩下: 編譯器如何依據(jù)泛型信息在編譯時進(jìn)行類型安全檢查。

第一點:
在(泛型類定義,泛型接口方法和函數(shù))定義中,編譯器如何確定具體泛型類型。

對于泛型類定義:
(通常一個變量引用的聲明類型來決定,或者實例化對象時指定)
如果泛型類定義是(如:public interface Map{} ),
現(xiàn)在有一個變量聲明,Map map; 那么這時編譯器就認(rèn)定 map變量的K的具體類型為String, V的具體類型為Integer。
又如,有一個實例化對象 new HashMap();那么這時編譯器就認(rèn)定 該對象的K的具體類型為String, V的具體類型為Integer。

對于 泛型接口方法和函數(shù)(包括實例化對象時的構(gòu)造函數(shù)) :
編譯器確定具體泛型類型是通過方法簽名中的 方法參數(shù) 或者 方法返回值。
(1)通過 方法參數(shù) 來確定 具體泛型類型。
void java.util.Collections.sort(List list, Comparator c)
(2)通過 方法返回值 來確定 具體泛型類型。
List java.util.Collections.emptyList()
(3)構(gòu)造函數(shù)
java.util.ArrayList.ArrayList(Collection c)

第二點:
在(泛型類定義,泛型接口方法和函數(shù))中的泛型聲明在編譯器中的作用域(泛型聲明的影響范圍)和對應(yīng)關(guān)系。

泛型類定義的泛型聲明在整個類定義中都有效。
如果在泛型類定義中有泛型聲明,(如:public interface Map{} ),則整個類定義中有如果出現(xiàn) A 或者 B 的地方都會跟隨類定義的泛型聲明

泛型接口方法和函數(shù)的泛型聲明在方法體和方法簽名有效。如果在泛型接口方法和函數(shù)上聲明了自己的泛型聲明則獨立開辟一個新的作用域,與類定義的泛型聲明區(qū)分開。

public class CopyOfGenericCollection {
    
    // 在泛型接口方法和函數(shù)中新開辟一個泛型聲明作用域
    // 這里的泛型聲明A和B,與類定義中的A和B 是沒有關(guān)系。
    public  Map unmodifiableMap1(Map m) {
        return null;
    }
    
    // 沿用泛型類定義的泛型聲明
    public Map unmodifiableMap2(Map m) {
        return null;
    }
}

// 測試

public class Test {
    public static void main(String[] args) {
        CopyOfGenericCollection extend = new CopyOfGenericCollection();
        
        // 可以看到map1變量的類型為Map
        Map map1 = extend.unmodifiableMap1(null);
        
        // 可以看到map2變量的類型為Map
        Map map2 = extend.unmodifiableMap2(null);
    }
}

最后
編譯的類型安全檢查,最基本的就是類型轉(zhuǎn)換,我們知道類型向上轉(zhuǎn)型是安全。
所以要使包含泛型的代碼中通過編譯器的編譯,我們要求賦值語句的都是,子類賦值父類,這就引入了 泛型系統(tǒng)的類型繼承關(guān)系。

相同類型參數(shù)的泛型類的關(guān)系取決于泛型類自身的繼承體系結(jié)構(gòu)。
即List是Collection 的子類型,List可以替換Collection。這種情況也適用于帶有上下界的類型聲明。

當(dāng)泛型類的類型聲明中使用了通配符的時候, 其子類型可以在兩個維度上分別展開。
如對Collection來說,其子類型可以在Collection這個維度上展開,即List和Set等;
也可以在Number這個層次上展開,即Collection和 Collection等。
如此循環(huán)下去,ArrayList和 HashSet等也都算是Collection的子類型。
如果泛型類中包含多個類型參數(shù)(如:Map),則對于每個類型參數(shù)分別應(yīng)用上面的規(guī)則。

Collection col_number = null;
List list_number = null;
Set set_number = null;
Collection col_double = null;
Collection col_integer = null;
HashSet hashSet_double = null;
ArrayList arrayList_integer = null;

col_number = list_number;
col_number = set_number;
col_number = col_double;
col_number = col_integer;
col_number = hashSet_double;
col_number = arrayList_integer;

Collection col_number_super = null;
Collection col_list_super = null;
Collection col_col_super = null;
Collection col_arrayList_super = null;

// col_number_super = col_number;// compile error
// col_number = col_number_super;// compile error
col_number_super = (Collection) col_number;
col_number = (Collection) col_number_super;
col_list_super = col_col_super;
// col_col_super = col_list_super; // compile error
// col_list_super = col_arrayList_super; // compile error

Map map_generic = null;
Map map_number_list = null;
Map map_integer_arrayList = null;
Map map_integer_col = null;
Map map_generic_super = null;
map_generic = map_number_list;
map_generic = map_integer_arrayList;
// map_generic = map_integer_col; // compile error
// map_generic = map_generic_super; // compile error
// map_generic_super = map_generic; // compile error

Map map_generic_list_super = null;
Map map_generic_col_super = null;
map_generic_list_super = map_generic_col_super;
// map_generic_col_super = map_generic_list_super; // compile error

下面是摘錄自知乎的見解:
https://www.zhihu.com/questio...

PECS原則
最后看一下什么是PECS(Producer Extends Consumer Super)原則,已經(jīng)很好理解了:
1.頻繁往外讀取內(nèi)容的,適合用上界Extends。
2.經(jīng)常往里插入的,適合用下界Super。

? 如果要從集合中讀取類型T的數(shù)據(jù),并且不能寫入,可以使用 ? extends 通配符;(Producer Extends)
? 如果要從集合中寫入類型T的數(shù)據(jù),并且不需要讀取,可以使用 ? super 通配符;(Consumer Super)
? 如果既要存又要取,那么就不要使用任何通配符。

什么是上界?
下面代碼就是“上界通配符(Upper Bounds Wildcards)”:
Plate<? extends Fruit>
翻譯成人話就是:一個能放水果以及一切是水果派生類的盤子。再直白點就是:啥水果都能放的盤子。
Plate<? extends Fruit>是Plate以及Plate的基類。
在這個體系中,上界通配符 “Plate<? extends Fruit>” 覆蓋下圖中藍(lán)色的區(qū)域。

什么是下界?
相對應(yīng)的,“下界通配符(Lower Bounds Wildcards)”:
Plate<? super Fruit>
表達(dá)的就是相反的概念:一個能放水果以及一切是水果基類的盤子。Plate<? super Fruit>是Plate的基類,但不是Plate的基類。對應(yīng)剛才那個例子,Plate<? super Fruit>覆蓋下圖中紅色的區(qū)域。在這個體系中,上界通配符

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/70773.html

相關(guān)文章

  • java編程思想》—— 泛型

    摘要:引用泛型除了方法因不能使用外部實例參數(shù)外,其他繼承實現(xiàn)成員變量,成員方法,方法返回值等都可使用。因此,生成的字節(jié)碼僅包含普通的類,接口和方法。 為什么要使用泛型程序設(shè)計? 一般的類和方法,只能使用具體的類型:要么是基本類型,要么是自定義類的對應(yīng)類型;如果要編寫可以應(yīng)用于多種類型的代碼,這種刻板的限制對代碼的束縛就會很大。----摘自原書Ordinary classes and meth...

    CODING 評論0 收藏0
  • Java知識點總結(jié)(Java泛型

    摘要:知識點總結(jié)泛型知識點總結(jié)泛型泛型泛型就是參數(shù)化類型適用于多種數(shù)據(jù)類型執(zhí)行相同的代碼泛型中的類型在使用時指定泛型歸根到底就是模版優(yōu)點使用泛型時,在實際使用之前類型就已經(jīng)確定了,不需要強制類型轉(zhuǎn)換。 Java知識點總結(jié)(Java泛型) @(Java知識點總結(jié))[Java, Java泛型] [toc] 泛型 泛型就是參數(shù)化類型 適用于多種數(shù)據(jù)類型執(zhí)行相同的代碼 泛型中的類型在使用時指定 泛...

    linkin 評論0 收藏0
  • 聊聊Java泛型及實現(xiàn)

    摘要:靜態(tài)變量是被泛型類的所有實例所共享的。所以引用能完成泛型類型的檢查。對于這個類型系統(tǒng),有如下的一些規(guī)則相同類型參數(shù)的泛型類的關(guān)系取決于泛型類自身的繼承體系結(jié)構(gòu)。事實上,泛型類擴展都不合法。 前言 和C++以模板來實現(xiàn)靜多態(tài)不同,Java基于運行時支持選擇了泛型,兩者的實現(xiàn)原理大相庭徑。C++可以支持基本類型作為模板參數(shù),Java卻只能接受類作為泛型參數(shù);Java可以在泛型類的方法中取得...

    lewif 評論0 收藏0
  • 淺析Java泛型

    摘要:泛型類在類的申明時指定參數(shù),即構(gòu)成了泛型類。換句話說,泛型類可以看成普通類的工廠。的作用就是指明泛型的具體類型,而類型的變量,可以用來創(chuàng)建泛型類的對象。只有聲明了的方法才是泛型方法,泛型類中的使用了泛型的成員方法并不是泛型方法。 什么是泛型? 泛型是JDK 1.5的一項新特性,它的本質(zhì)是參數(shù)化類型(Parameterized Type)的應(yīng)用,也就是說所操作的數(shù)據(jù)類型被指定為一個參數(shù),...

    godiscoder 評論0 收藏0
  • 初探Java類型擦除

    摘要:可以看到,如果我們給泛型類制定了上限,泛型擦除之后就會被替換成類型的上限。相應(yīng)的,泛型類中定義的方法的類型也是如此。參考語言類型擦除下界通配符和的區(qū)別 本篇博客主要介紹了Java類型擦除的定義,詳細(xì)的介紹了類型擦除在Java中所出現(xiàn)的場景。 1. 什么是類型擦除 為了讓你們快速的對類型擦除有一個印象,首先舉一個很簡單也很經(jīng)典的例子。 // 指定泛型為String List list1 ...

    DevTalking 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<