亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

Java 泛型詳解

2019-11-11 06:56:04
字體:
來源:轉載
供稿:網友

學習java的同學注意了?。。?nbsp;學習過程中遇到什么問題或者想獲取學習資源的話,歡迎加入Java學習交流群,群號碼:183993990  我們一起學Java!

泛型概述

Java泛型(generics)是JDK 5中引入的一個新特性,允許在定義類和接口的時候使用類型參數(type parameter)。聲明的類型參數在使用時用具體的類型來替換。

優缺點

從好的方面來說,泛型的引入可以解決之前的集合類框架在使用過程中通常會出現的運行時刻類型錯誤,因為編譯器可以在編譯時刻就發現很多明顯的錯誤。而從不好的地方來說,為了保證與舊有版本的兼容性,Java泛型的實現上存在著一些不夠優雅的地方。當然這也是任何有歷史的編程語言所需要承擔的歷史包袱。后續的版本更新會為早期的設計缺陷所累。

舉例

List作為形式參數,那么如果嘗試將一個List的對象作為實際參數傳進去,卻發現無法通過編譯。雖然從直覺上來說,Object是String的父類,這種類型轉換應該是合理的。但是實際上這會產生隱含的類型轉換問題,因此編譯器直接就禁止這樣的行為。

類型擦除

正確理解泛型概念的首要前提是理解類型擦除(type erasure)。

Java中的泛型基本上都是在編譯器這個層次來實現的。

在生成的Java字節代碼中是不包含泛型中的類型信息的。使用泛型的時候加上的類型參數,會被編譯器在編譯的時候去掉。這個過程就稱為類型擦除。

如在代碼中定義的List和List等類型,在編譯之后都會變成List。JVM看到的只是List,而由泛型附加的類型信息對JVM來說是不可見的。Java編譯器會在編譯時盡可能的發現可能出錯的地方,但是仍然無法避免在運行時刻出現類型轉換異常的情況。類型擦除也是Java的泛型實現方式與C++模板機制實現方式之間的重要區別。

很多泛型的奇怪特性都與這個類型擦除的存在有關

1.泛型類并沒有自己獨有的Class類對象。比如并不存在List.class或是List.class,而只有List.class。

2.靜態變量是被泛型類的所有實例所共享的。對于聲明為MyClass的類,訪問其中的靜態變量的方法仍然是 MyClass.myStaticVar。不管是通過new MyClass還是new MyClass創建的對象,都是共享一個靜態變量。

3.泛型的類型參數不能用在Java異常處理的catch語句中。因為異常處理是由JVM在運行時刻來進行的。由于類型信息被擦除,JVM是無法區分兩個異常類型MyException和MyException的。對于JVM來說,它們都是 MyException類型的。也就無法執行與異常對應的catch語句。

類型擦除的過程

類型擦除的基本過程也比較簡單,首先是找到用來替換類型參數的具體類。這個具體類一般是Object。如果指定了類型參數的上界的話,則使用這個上界。把代碼中的類型參數都替換成具體的類。同時去掉出現的類型聲明,即去掉<>的內容。比如T get()方法聲明就變成了Object get();List就變成了List。接下來就可能需要生成一些橋接方法(bridge method)。這是由于擦除了類型之后的類可能缺少某些必須的方法。

實例分析

了解了類型擦除機制之后,就會明白編譯器承擔了全部的類型檢查工作。編譯器禁止某些泛型的使用方式,正是為了確保類型的安全性。以上面提到的List和List為例來具體分析:

public void inspect(List<Object> list) {        for (Object obj : list) {                System.out.PRintln(obj);        }        list.add(1); //這個操作在當前方法的上下文是合法的。 }public void test() {        List<String> strs = new ArrayList<String>();        inspect(strs); //編譯錯誤 }

這段代碼中,inspect方法接受List作為參數,當在test方法中試圖傳入List的時候,會出現編譯錯誤。假設這樣的做法是允許的,那么在inspect方法就可以通過list.add(1)來向集合中添加一個數字。這樣在test方法看來,其聲明為List的集合中卻被添加了一個Integer類型的對象。這顯然是違反類型安全的原則的,在某個時候肯定會拋出ClassCastException。因此,編譯器禁止這樣的行為。編譯器會盡可能的檢查可能存在的類型安全問題。對于確定是違反相關原則的地方,會給出編譯錯誤。當編譯器無法判斷類型的使用是否正確的時候,會給出警告信息。

泛型類

容器類應該算得上最具重用性的類庫之一。先來看一個沒有泛型的情況下的容器類如何定義:

public class Container {    private String key;    private String value;    public Container(String k, String v) {        key = k;        value = v;    }    public String getKey() {        return key;    }    public void setKey(String key) {        this.key = key;    }    public String getValue() {        return value;    }    public void setValue(String value) {        this.value = value;    }}

Container類保存了一對key-value鍵值對,但是類型是定死的,也就說如果我想要創建一個鍵值對是String-Integer類型的,當前這個Container是做不到的,必須再自定義。那么這明顯重用性就非常低。

當然,我可以用Object來代替String,并且在Java SE5之前,我們也只能這么做,由于Object是所有類型的基類,所以可以直接轉型。但是這樣靈活性還是不夠,因為還是指定類型了,只不過這次指定的類型層級更高而已,有沒有可能不指定類型?有沒有可能在運行時才知道具體的類型是什么?

所以,就出現了泛型。

public class Container<K, V> {    private K key;    private V value;    public Container(K k, V v) {        key = k;        value = v;    }    public K getKey() {        return key;    }    public void setKey(K key) {        this.key = key;    }    public V getValue() {        return value;    }    public void setValue(V value) {        this.value = value;    }}

在編譯期,是無法知道K和V具體是什么類型,只有在運行時才會真正根據類型來構造和分配內存??梢钥匆幌卢F在Container類對于不同類型的支持情況:

public class Main {    public static void main(String[] args) {        Container<String, String> c1 = new Container<String, String>("name", "findingsea");        Container<String, Integer> c2 = new Container<String, Integer>("age", 24);        Container<Double, Double> c3 = new Container<Double, Double>(1.1, 2.2);        System.out.println(c1.getKey() + " : " + c1.getValue());        System.out.println(c2.getKey() + " : " + c2.getValue());        System.out.println(c3.getKey() + " : " + c3.getValue());    }}
輸出:name : findingseaage : 241.1 : 2.2

泛型接口

在泛型接口中,生成器是一個很好的理解,看如下的生成器接口定義:

public interface Generator<T> {    public T next();}然后定義一個生成器類來實現這個接口:public class FruitGenerator implements Generator<String> {    private String[] fruits = new String[]{"Apple", "Banana", "Pear"};    @Override    public String next() {        Random rand = new Random();        return fruits[rand.nextInt(3)];    }}調用:public class Main {    public static void main(String[] args) {        FruitGenerator generator = new FruitGenerator();        System.out.println(generator.next());        System.out.println(generator.next());        System.out.println(generator.next());        System.out.println(generator.next());    }}輸出:BananaBananaPearBanana

泛型方法

一個基本的原則是:無論何時,只要你能做到,你就應該盡量使用泛型方法。也就是說,如果使用泛型方法可以取代將整個類泛化,那么應該有限采用泛型方法。下面來看一個簡單的泛型方法的定義:

public class Main {    public static <T> void out(T t) {        System.out.println(t);    }    public static void main(String[] args) {        out("findingsea");        out(123);        out(11.11);        out(true);    }}

可以看到方法的參數徹底泛化了,這個過程涉及到編譯器的類型推導和自動打包,也就說原來需要我們自己對類型進行的判斷和處理,現在編譯器幫我們做了。這樣在定義方法的時候不必考慮以后到底需要處理哪些類型的參數,大大增加了編程的靈活性。

再看一個泛型方法和可變參數的例子:

public class Main {    public static <T> void out(T... args) {        for (T t : args) {            System.out.println(t);        }    }    public static void main(String[] args) {        out("findingsea", 123, 11.11, true);    }}

通配符與上下界

在使用泛型類的時候,既可以指定一個具體的類型,如List就聲明了具體的類型是String;也可以用通配符?來表示未知類型,如List

類型系統

在Java中,大家比較熟悉的是通過繼承機制而產生的類型體系結構。比如String繼承自Object。根據Liskov替換原則,子類是可以替換父類的。當需要Object類的引用的時候,如果傳入一個String對象是沒有任何問題的。但是反過來的話,即用父類的引用替換子類引用的時候,就需要進行強制類型轉換。編譯器并不能保證運行時刻這種轉換一定是合法的。這種自動的子類替換父類的類型轉換機制,對于數組也是適用的。 String[]可以替換Object[]。但是泛型的引入,對于這個類型系統產生了一定的影響。正如前面提到的List是不能替換掉List的。

引入泛型之后的類型系統增加了兩個維度:

一個是類型參數自身的繼承體系結構,另外一個是泛型類或接口自身的繼承體系結構。第一個指的是對于 List和List這樣的情況,類型參數String是繼承自Object的。而第二種指的是 List接口繼承自Collection接口。對于這個類型系統,有如下的一些規則:

相同類型參數的泛型類的關系取決于泛型類自身的繼承體系結構。

即List是Collection 的子類型,List可以替換Collection。這種情況也適用于帶有上下界的類型聲明。

當泛型類的類型聲明中使用了通配符的時候, 其子類型可以在兩個維度上分別展開。如對Collection

泛型的命名規范

為了更好地去理解泛型,我們也需要去理解java泛型的命名規范。為了與java關鍵字區別開來,java泛型參數只是使用一個大寫字母來定義。各種常用泛型參數的意義如下:

E — Element,常用在java Collection里,如:List,Iterator,SetK,V — Key,Value,代表Map的鍵值對N — Number,數字T — Type,類型,如String,Integer等等S,U,V etc. – 2nd, 3rd, 4th 類型,和T的用法一樣

學習Java的同學注意了?。?! 學習過程中遇到什么問題或者想獲取學習資源的話,歡迎加入Java學習交流群,群號碼:183993990  我們一起學Java!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品极品尤物在线观看| 欧美自拍视频在线| 亚洲人成电影在线播放| 中文字幕欧美亚洲| 精品亚洲一区二区| 欧美做爰性生交视频| 91精品久久久久久久久中文字幕| 国产欧美日韩精品丝袜高跟鞋| 日韩亚洲欧美中文高清在线| 国产在线高清精品| 久久男人av资源网站| 色偷偷av一区二区三区乱| 久久九九国产精品怡红院| 亚洲精品自在久久| 国产一区二区激情| 色妞久久福利网| 九九精品在线观看| 日韩精品中文字幕在线观看| 国产精品伦子伦免费视频| 久久成人一区二区| 亚洲精品美女视频| 粉嫩老牛aⅴ一区二区三区| 成人黄色av免费在线观看| 韩国国内大量揄拍精品视频| 亚洲丝袜在线视频| 精品无人区乱码1区2区3区在线| 最新91在线视频| 亚洲综合成人婷婷小说| 国产精品成久久久久三级| 久久影院资源网| 中文字幕久久亚洲| 精品美女永久免费视频| 亚洲精品成人免费| 亚洲字幕一区二区| 色综合91久久精品中文字幕| 国产精品精品久久久久久| 国产97人人超碰caoprom| 国产精品私拍pans大尺度在线| 色综合天天狠天天透天天伊人| 国产午夜精品美女视频明星a级| 5566成人精品视频免费| 国产精品久久久久av| 裸体女人亚洲精品一区| 精品国产老师黑色丝袜高跟鞋| 久久久久久18| 欧美成人中文字幕在线| 欧美整片在线观看| 国产色婷婷国产综合在线理论片a| 国产精品三级美女白浆呻吟| 国产精品对白刺激| 欧美福利视频在线观看| 欧美日韩国产综合视频在线观看中文| 18性欧美xxxⅹ性满足| 亚洲午夜久久久影院| 福利视频第一区| 日本在线精品视频| 欧美乱大交xxxxx另类电影| 一色桃子一区二区| 亚洲欧美日韩在线高清直播| 91久久国产婷婷一区二区| 国产成人一区二区| 欧美在线一级va免费观看| 久久6精品影院| 欧美另类高清videos| 国产精品久久久久久av福利软件| 国产精自产拍久久久久久蜜| 成人a视频在线观看| 国产精品女人久久久久久| 亚洲天堂av图片| 色综合久久88色综合天天看泰| 亚洲www在线观看| 成人信息集中地欧美| 搡老女人一区二区三区视频tv| 日本人成精品视频在线| 在线精品国产成人综合| 亚洲精品女av网站| 少妇高潮久久77777| 欧美日韩国产一区二区三区| 欧美午夜性色大片在线观看| 精品国产精品三级精品av网址| 7777精品久久久久久| 欧美日韩在线一区| 国产日韩欧美日韩大片| 日韩成人在线电影网| 国产精品美女视频网站| 777午夜精品福利在线观看| 亚洲a一级视频| 久久精品国产亚洲精品| 成人在线小视频| 一区二区亚洲精品国产| 国产精品对白刺激| 欧美日韩一区二区在线播放| 国产在线精品一区免费香蕉| 久久久午夜视频| 国产精品无av码在线观看| 日韩精品中文在线观看| 欧美国产视频一区二区| 亚洲欧美国内爽妇网| 68精品国产免费久久久久久婷婷| 午夜精品久久久久久久99热浪潮| 欧美大片在线影院| 77777少妇光屁股久久一区| 欧美成人中文字幕在线| 欧美理论电影在线观看| 欧美亚洲国产日本| 日韩av成人在线观看| 精品久久久国产精品999| 国产亚洲精品久久久久久777| 欧美在线视频导航| 一区二区三区无码高清视频| 日韩中文字幕在线| 伦理中文字幕亚洲| 亚洲美女视频网| 亚洲一区二区三区在线免费观看| 精品久久久国产精品999| 久久精品国产亚洲| 欧美精品在线免费播放| 亚洲精品v欧美精品v日韩精品| 日本韩国欧美精品大片卡二| 在线播放日韩欧美| 亚洲人成在线观看| 国产精品福利在线观看网址| 色yeye香蕉凹凸一区二区av| 成人欧美一区二区三区黑人| 久久久国产精品亚洲一区| 国产不卡精品视男人的天堂| 亚洲精品电影在线观看| 国产精品观看在线亚洲人成网| 久久精品视频在线播放| 欧美日韩第一视频| 欧美激情一级欧美精品| 欧美成人精品在线观看| 国产精品一区二区三区久久久| 色偷偷888欧美精品久久久| 亚洲午夜精品久久久久久久久久久久| 日韩电影中文字幕| 亚洲国产一区二区三区在线观看| 91香蕉嫩草神马影院在线观看| 国产欧美久久久久久| 日韩精品视频免费专区在线播放| 日本久久久久亚洲中字幕| 中文字幕一区二区精品| 国产精品自拍小视频| 日韩精品欧美国产精品忘忧草| 91tv亚洲精品香蕉国产一区7ujn| 欧美美最猛性xxxxxx| 国产精品极品尤物在线观看| 中文.日本.精品| 亚洲福利在线看| 精品国内自产拍在线观看| 最近2019中文字幕大全第二页| 国产日韩一区在线| 精品亚洲一区二区三区在线播放| 欧美精品www| 日韩国产精品视频| 日韩精品欧美国产精品忘忧草| 韩国欧美亚洲国产| 国产欧美一区二区三区久久| 狠狠久久五月精品中文字幕| 欧美乱大交做爰xxxⅹ性3| 国产精品久久久久久久久久东京| www.美女亚洲精品| 久久影院免费观看| 国产精品96久久久久久又黄又硬|