Java筆記:泛型

來源:互聯網
上載者:User

標籤:允許   hid   min   自動   來替   資訊   gets   return   super   

一、簡單一實例

class Solution<T> {    private T obj;    Solution(T obj) {        this.obj = obj;    }    public T getObj() {        return obj;    }    public static void main(String[] args) {        Solution<Integer> solution = new Solution<>(100);        Object obj = solution.getObj();        System.out.println(obj.getClass().getName());//java.lang.Integer        System.out.println(obj);//100    }}
View Code


二、型別安全

若簡單地使用Object來替代泛型並確保類型轉換正確,那麼即使不適用泛型也能得到相同的功能。但是如果類型轉換不正確,程式就會在運行時發生錯誤,使用泛型可以自動確保型別安全,這個過程中消除了手動輸入類型轉換以及類型檢查的需要,運行時的錯誤就可以轉換為編譯時間的錯誤,這是泛型的主要優勢。

 

三、多個型別參數

class Solution<T, V> {    private T objA;    private V objB;    Solution(T objA, V objB) {        this.objA = objA;        this.objB = objB;    }    public T getObjA() {        return objA;    }    public V getObjB() {        return objB;    }    public static void main(String[] args) {        Solution<Character, Integer> solution = new Solution<>(‘0‘, 0);        System.out.println(solution.getObjA());        System.out.println(solution.getObjB());    }}
View Code

 

四、有界類型

通過指定超類限制能夠傳遞給型別參數的類型。

class Solution<T extends Number> {    private T[] arr;    double getSum() {        double sum = 0;        for (T i : arr)            sum += i.doubleValue();        return sum;    }    Solution(T... nums) {        arr = nums;    }    public static void main(String[] args) {        Solution<Integer> solution = new Solution<>(1, 2, 3, 4, 5);        System.out.println(solution.getSum());    }}
View Code

除了指定超類作為邊界之外,還可以指定介面作為邊界。

五、萬用字元參數

boolean sameSum(Solution<T> ob) {        return getSum() == ob.getSum();}
View Code

假設我們需要比較具有不同泛型參數的相同類型對象,上述代碼並不能滿足要求。只有當比較對象具有相同的泛型參數時,上述代碼才可以被調用。正確的解決方案需要用到萬用字元,萬用字元同樣可指定為有界。

class Solution<T extends Number> {    private T[] arr;    double getSum() {        double sum = 0;        for (T i : arr)            sum += i.doubleValue();        return sum;    }    boolean sameSum(Solution<? extends Number> ob) {        return getSum() == ob.getSum();    }    Solution(T... nums) {        arr = nums;    }    public static void main(String[] args) {        Solution<Integer> solutionA = new Solution<>(1, 2, 3, 4, 5);        Solution<Double> solutionB = new Solution<>(5.0, 4.0, 3.0, 2.0, 1.0);        System.out.println(solutionA.sameSum(solutionB));//true    }}
View Code

 

六、泛型方法

class Solution {    static <T extends Number, V extends Number> boolean contain(T[] arr, V x) {        for (int i = 0; i < arr.length; i++)            if (arr[i].doubleValue() == x.doubleValue())                return true;        return false;    }    public static void main(String[] args) {        Double[] arr = {1.0, 2.0, 3.0, 4.0, 5.0};        System.out.println(contain(arr, 1));    }}
View Code

建構函式同樣支援泛型。

class Solution {    private double number;    <T extends Number> Solution(T t) {        number = t.doubleValue();    }}
View Code

 

七、泛型介面

泛型介面與泛型類相似。

interface MinMax<T extends Comparable<T>> {    T min();    T max();}class Solution<T extends Comparable<T>> implements MinMax<T> {    private T[] arr;    @Override    public T min() {        T res = arr[0];        for (int i = 1; i < arr.length; i++)            if (res.compareTo(arr[i]) > 0)                res = arr[i];        return res;    }    @Override    public T max() {        T res = arr[0];        for (int i = 1; i < arr.length; i++)            if (res.compareTo(arr[i]) < 0)                res = arr[i];        return res;    }    Solution(T... nums) {        arr = nums;    }    public static void main(String[] args) {        Solution<Integer> ob = new Solution<>(1, 2, 3, 4, 5);        System.out.println(ob.min());        System.out.println(ob.max());    }}
View Code

 

八、曆史遺留

早期的Java是不支援泛型的,現在仍然存在大量曆史遺留代碼。為了使這些遺留代碼保留功能同時又和泛型相容,Java允許使用泛型類而不提供任何型別參數,這會為類建立原始類型。原始類型與不使用泛型的遺留代碼是相容的,但失去了泛型的型別安全。本質上就是使用Object替換了型別參數所表示的類型。

class Solution<T> {    private T ob;    Solution(T ob) {        this.ob = ob;    }    T getOb() {        return ob;    }    public static void main(String[] args) {        Solution solution = new Solution(new String("Hello World"));        System.out.println(solution.getOb());    }}
View Code

 

九、泛型類層次

使用泛型超類。

class A<T> {    T a;    A(T a) {        this.a = a;    }    T getA() {        return a;    }}class B<T, V> extends A<T> {    V b;    B(T a, V b) {        super(a);        this.b = b;    }    V getB() {        return b;    }}
View Code

泛型層次比較。

class Solution {    public static void main(String[] args) {        B<String, String> obB = new B<>("Hello", "World");        System.out.println(obB instanceof A<?>);//true    }}
View Code

當需要對泛型類進行強制轉換時,必須確保其相互相容並且泛型參數相同。

 

十、擦除

為了相容以前的Java版本,對Java語言的文法或虛擬機器所做的任何修改必須避免破壞以前的代碼,所以Java使用擦除實現泛型。

擦除的工作原理:編譯Java代碼時,所有泛型資訊被擦除。那麼必須使用他們的界定類型替換型別參數,如果沒有顯式指定界定類型,就會使用Object。之後進行適當的類型轉換以保持與型別參數所指定類型的相容。這意味著允許時時沒有型別參數的,Java泛型只是一種原始碼機制,運行時的類型轉換必然會帶來開銷。

 

十一、模糊性錯誤

class Solution<T, V> {    private T a;    private V b;    Solution(T a, V b) {        this.a = a;        this.b = b;    }    void set(T a) {        this.a = a;    }    void set(V b) {        this.b = b;    }}
View Code

上述代碼出現了模糊性錯誤,當T和V為相同類型時,無法確定調用的方法。

 

十二、限制

  • 不能執行個體化型別參數的對象或數組。
  • 靜態成員不能使用在類中聲明的型別參數。
  • 泛型類不能擴充Throwable,即不能建立泛型異常類。

若要執行個體化泛型對象的數組,需要使用萬用字元。

class Solution<T> {    public static void main(String[] args) {        Solution<Integer>[] solutionsA = new Solution<Integer>[10];//錯誤        Solution<?>[] solutionsB = new Solution<?>[10];//正確    }}
View Code

 

Java筆記:泛型

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.