瞭解泛型

本文主要通過代碼來展示

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 1.泛型方法&非泛型方法
 * 2.無限定符
 * 3.泛型上限&泛型下限
 * 4.特殊方法equals
 * 5.泛型擦除&利用反射擦除泛型
 * 6.泛型的參數類型
 * 7.靜態常量或靜態方法中的泛型
 * 8.泛型數組
 * 9.泛型與可變參數
 * @param <E>
 */
public class Generator<E> {
    /**
     * E的類型需要與聲明類時的類型一致,這裏不是泛型方法
     * @param element
     * @return
     */
    E next(E element){return null;}

    /**
     * E的類型可以與聲明類時的類型不一致,這裏是泛型方法
     * @param element
     * @param <E>
     * @return
     */
    <E> E upload(E element){return null;}

    /**
     * 當具體類型不確定的時候,這個通配符就是 ?,可以看成所有類型的父類型
     * @param element
     */
    void show(Generator<?> element){}

    /**
     * 方法內是被無限定符修飾的參數,它隱略的表達了一個意圖,或者說可以是限定,那就是這個方法不需要關心List中的真實類型。因爲它是未知的。
     * 所以只能使用List中無關類型的方法。
     *
     * <?>提供了只讀的功能,也就是它刪減了增加具體類型元素的能力,只保留與具體類型無關的功能。
     * 它不管裝載在這個容器內的元素是什麼類型,它只關心元素的數量、容器是否爲空
     * @param list
     */
    public void showTest(List<?> list){
        //list.add(12); //報錯
        //list.add("hello");// 報錯

        Object o = list.get(0);
        int size = list.size();
    }

    /**
     * 泛型方法的基本介紹
     * @param tClass 傳入的泛型實參
     * @return T 返回值爲T類型
     * 說明:
     *     1)public 與 返回值中間<T>非常重要,可以理解爲聲明此方法爲泛型方法。
     *     2)只有聲明瞭<T>的方法纔是泛型方法,泛型類中的使用了泛型的成員方法並不是泛型方法。
     *     3)<T>表明該方法將使用泛型類型T,此時纔可以在方法中使用泛型類型T。
     *     4)與泛型類的定義一樣,此處T可以隨便寫爲任意標識,常見的如T、E、K、V等形式的參數常用於表示泛型。
     */
    <K> K left(Class<K> tClass){return null;}

    /**
     * 爲泛型添加上邊界,即傳入的類型實參必須是指定類型的子類型
     * @param tClass
     */
    void rigth(Generator<? extends Number> tClass){}

    /**
     * 爲泛型添加下邊界,即傳入的類型實參必須是指定類型的父類型
     * @param element
     */
    void load(Generator<? super E> element){}

    /**
     * 在泛型方法中添加上下邊界限制的時候,必須在權限聲明與返回值之間的<T>上添加上下邊界,即在泛型聲明的時候添加
     * @param element
     * @param <E>
     * @return
     */
    public <E extends Number> E down(E element){return null;}

    /**
     * 因爲泛型擦除後該方法就會變成
     *  boolean equals(Object obj);
     *  和Object.equal()衝突
     */
    //boolean equals(E element){} //這是錯誤的

    /**
     * 泛型類中的靜態方法和靜態變量不可以使用泛型類所聲明的泛型類型參數
     * 因爲泛型類中的泛型參數的實例化是在定義對象的時候指定的,而靜態變量和靜態方法不需要使用對象來調用。
     * 對象都沒有創建,如何確定這個泛型參數是何種類型,所以當然是錯誤的
     * @param element
     * @return
     */
    //public static E getInstance(E element){return null;} // 這是錯誤的

    /**
     * 使用方法時傳入指定的類型:這個是泛型方法
     * 因爲這是一個泛型方法,在泛型方法中使用的T是自己在方法中定義的T,而不是泛型類中的T
     * @param element
     * @param <E>
     * @return
     */
    public static <E> E getEntity(E element){return null;}//這是正確的

    /**
     * 泛型類型不能使用基本類型
     * @param element
     */
    //public void addEntity(Generator<int> element){ } // 這是錯誤的


    /**
     * 泛型只在編譯階段起作用,運行時會把泛型擦除,所以會輸出true
     * @param args
     */
    /*public static void main(String[] args){
        Generator<String> entity1 = new Generator<>();
        Generator<Integer> entity2 = new Generator<>();
        System.out.println(entity1.getClass() == entity2.getClass());//true
    }*/

    /**
     * 泛型數組問題
     * @param args
     */
    /*public static void main(String[] args) {
        *//**
         * 原因還是類型擦除帶來的影響
         *//*
        // List<String>[] list1 = new ArrayList<String>[10]; //這是錯誤的

        *//**
         * 藉助於無限定通配符卻可以,前面講過 ?代表未知類型,所以它涉及的操作都基本上與類型無關,
         * 因此 jvm 不需要針對它對類型作判斷,因此它能編譯通過,但是,只提供了數組中的元素因爲通配符原因,它只能讀,不能寫。
         * 比如,上面的 v 這個局部變量,它只能進行 get() 操作,不能進行 add() 操作
         *//*
        List<?>[] list2 = new ArrayList<?>[10];//這是正確的
        list2[1] = new ArrayList<String>();
        List<?> list3 = list2[1];
    }*/

    /**
     * 利用泛型擦除向集合中添加元素
     * @param args
     * @throws ClassNotFoundException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    /*public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        //list.add(1); // 這是錯誤的,類型檢查不通過

        // 通過反射擦除類型,添加到集合中
        Class<?> clazz = Class.forName("java.util.ArrayList");
        Method addMethod = clazz.getMethod("add", Object.class);
        addMethod.invoke(list,1);
        System.out.println(list); // [a,b,1]
    }*/

    /**
     * 泛型與可變參數
     * @param args
     * @param <E>
     */
    public static <E> void printArray(E... args){
        for(E e : args){
            System.out.println(e);
        }
    }

    public static void main(String[] args) {
        printArray(1,2,3,"a","b","c");
    }

}

demo2.實現泛型接口的泛型類

public interface GeneratorA<E> {
    E getEntity();
}

/**
 * public class GeneratorAImpl implements GeneratorA<E> 這樣會報錯
 * 未傳入泛型實參時,與泛型類的定義相同,在聲明類的時候,需將泛型的聲明也一起加到類中
 */
public class GeneratorAImpl<E> implements GeneratorA<E>{
    @Override
    public E getEntity() {
        return null;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章