1. 程式人生 > >泛型的基本介紹

泛型的基本介紹

1.為什麼需要泛型?泛型是什麼?

public class WhyGeneric {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("aaa");
        list.add(111);
        for (int i = 0; i < list.size(); i++) {
            String s = (String) list.get(i);
            System.out.println(s);
        }
    }
}

上面例子執行會報ClassCastException錯誤,list裡面放入了String和Integer型別的資料,編譯時不報錯,讀取執行時報錯,加上泛型在編譯時我們就不能給集合中新增兩種以以上型別的資料。

泛型是引數化的型別,在具體使用的過程中才會變成具體的型別。泛型的型別不可以是基本型別,只能是引用型別!

2.泛型擦除

    @Test
    public void caiChu() {
        List<String> L1 = new ArrayList<String>();
        List<Integer>
L2 = new ArrayList<Integer>(); Class c1 = L1.getClass(); Class c2 = L2.getClass(); if(L1.equals(L2)) { System.out.println("泛型擦除了"); } }

輸出結果是“泛型擦除了”,證明在位元組碼中泛型就消失了。

3.泛型的使用:
* 泛型類

/**
 * Created by Alsidun on 2018/7/12.
 * 泛型類
 */
public class
Generic<T> {
private T key; public Generic(T key) { this.key = key; } public T getKey() { return key; } } public class TestGenericClass { public static void main(String[] args) { Generic<String> gs = new Generic<String>("abc"); Generic<Integer> gi = new Generic<>(1); System.out.println("傳入的引數是 " + gs.getKey()); System.out.println("傳入的引數是 " + gi.getKey()); //這裡不指定引數型別,那麼就是Object Generic ga = new Generic(1); Generic gb = new Generic(1.5555); Generic gc = new Generic(false); System.out.println("傳入的引數是 " + ga.getKey()); System.out.println("傳入的引數是 " + gb.getKey()); System.out.println("傳入的引數是 " + gc.getKey()); } } /* 傳入的引數是 abc 傳入的引數是 1 傳入的引數是 1 傳入的引數是 1.5555 */

上面的例子定義了一個泛型類及它的使用,只有在類例項化時才知道這個類的具體成員引數型別

  • 泛型介面
/**
 * Created by Alsidun on 2018/7/12.
 */
public interface GenericIntface<T> {
    T say();
}

/**
 * 未傳入泛型實參時,與泛型類的定義相同,在宣告類的時候,需將泛型的宣告也一起加到類中
 * AnimalGeneric implements GenericIntface<T>  報錯!!!
 * @param <T>
 */
class GenericImpl<T> implements GenericIntface<T> {
    @Override
    public T say() {
        return null;
    }
}

/**
 * 在實現類實現泛型介面時,如已將泛型型別傳入實參型別,則所有使用泛型的地方都要替換成傳入的實參型別
 */
class AnimalGeneric implements GenericIntface<String> {
    private String[] animal = new String[]{"dog", "cat", "pig"};
    @Override
    public String say() {
        System.out.println("輸出狗 " + animal[0]);
        return animal[1];
    }

    public static void main(String[] args) {
        AnimalGeneric ag = new AnimalGeneric();
        ag.say();
    }
}
  • 泛型方法
    泛型方法是指在呼叫方法的時候在指明方法的引數型別

public <T> T show(Generic<T> container)

/**
 * Created by Alsidun on 2018/7/12.
 * 泛型方法
 */
public class GenericFruit  {
    static class Fruit {
        @Override
        public String toString(){
            return  "fruit";
        }
    }

    static class Apple extends Fruit {
        @Override
        public String toString() {
            return "apple";
        }
    }

    static class Animal {
        @Override
        public String toString() {
            return "person";
        }
    }

    static class GenericTest<T> {
        public void show1(T t) {
            System.out.println("輸出 " + t.toString());
        }

        //此處的泛型可以和泛型類相同也可不同
        public <T> void show2(T t) {
            System.out.println("輸出 " + t.toString());
        }

        public <E> void show3(E t) {
            System.out.println("輸出 " + t.toString());
        }
    }

    public static void main(String[] args) {
        /*成員方法,變數,內部類同一級別,必須通過類的例項呼叫
        * 靜態方法裡面不可以訪問外部類的非靜態變數,普通內部類(都是靜態才可訪問)
        * 靜態訪問靜態
        * */
        Apple apple = new Apple();
        Animal animal = new Animal();

        GenericTest<String> gs = new GenericTest<String>();
        GenericTest<Fruit> gf = new GenericTest<Fruit>();

        gs.show1("abc");
        gf.show1(apple);
        //gf.show1(animal);  無法編譯通過
        gf.show2(apple);
        gf.show2("qwe");
        gf.show2(animal);
        gf.show3(apple);
        gf.show3(animal);
    }
}

這裡會輸出對應的物件

4.泛型的萬用字元
使用時不知道型別使用萬用字元
ArrayList<?> 代表Object
ArrayList<? extends List> List及其子類
ArrayList<? super List> List及其父類