成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Java泛型

lauren_liuling / 3096人閱讀

摘要:通過方法返回值來確定具體泛型類型。泛型類定義的泛型聲明在整個類定義中都有效。相同類型參數的泛型類的關系取決于泛型類自身的繼承體系結構。

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

泛型對于Java編程的作用:

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

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

編譯前的泛型類:

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é)碼反編譯工具進行反編譯后:

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

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

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

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

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

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

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

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

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

public class CopyOfGenericCollection {
    
    // 在泛型接口方法和函數中新開辟一個泛型聲明作用域
    // 這里的泛型聲明A和B,與類定義中的A和B 是沒有關系。
    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);
    }
}

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

相同類型參數的泛型類的關系取決于泛型類自身的繼承體系結構。
即List是Collection 的子類型,List可以替換Collection。這種情況也適用于帶有上下界的類型聲明。

當泛型類的類型聲明中使用了通配符的時候, 其子類型可以在兩個維度上分別展開。
如對Collection來說,其子類型可以在Collection這個維度上展開,即List和Set等;
也可以在Number這個層次上展開,即Collection和 Collection等。
如此循環(huán)下去,ArrayList和 HashSet等也都算是Collection的子類型。
如果泛型類中包含多個類型參數(如:Map),則對于每個類型參數分別應用上面的規(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)原則,已經很好理解了:
1.頻繁往外讀取內容的,適合用上界Extends。
2.經常往里插入的,適合用下界Super。

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

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

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

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

轉載請注明本文地址:http://m.hztianpu.com/yun/70773.html

相關文章

  • java編程思想》—— 泛型

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

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

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

    linkin 評論0 收藏0
  • 聊聊Java泛型及實現

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

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

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

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

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

    DevTalking 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<