1. 程式人生 > 其它 >【APICloud系列|34】免費使用的ChromeDebug 模組

【APICloud系列|34】免費使用的ChromeDebug 模組

技術標籤:JavaSE

泛型

1、泛型的概念

泛型的出現,可以讓我們少些程式碼,它的主要作用是解決型別的安全問題,不會因為將物件置於某個容器中而失去其型別。在泛型出現之前,Java提供了對Object型別引用的任意操作,即向上轉型和向下轉型,上轉型沒問題,但是向下轉型這種強制型別轉換是存在隱患的,因此Java提供了泛型機制。

Java泛型(generics)是JDK5中引入的一個新特性, 泛型提供了編譯時型別安全檢測機制,該機制允許程式設計師在編譯時檢測到非法的型別。泛型的本質是引數化型別,也就是說所操作的資料型別被指定為一個引數。

泛型並不是一種資料型別,而是一種特殊語法,對接收的資料型別進行了規定。如Map<String,String> map = new HashMap()。只允許字串型別資料作為Map集合的value值,不接受其他資料型別。使用泛型的好處是在程式碼書寫過程中可提高效率和資料型別安全,規避因資料型別不符合要求而造成的編譯錯誤,最突出的是避免了資料物件強制轉換,支援動態下確定資料型別。通常在集合中使用泛型。

以一個例子說明。

定義一個實體類:

public class T1 {

    private Object obj;

    public Object getObj() {
        return
obj; } public void setObj(Object obj) { this.obj = obj; } }

測試:

    public static void main(String[] args) {
        T1 t = new T1();
        // 上轉型
        t.setObj(new Boolean(true));
        System.out.println(t.getObj());
        T1 t2 = new T1();
        t2.setObj(new Float
(25.5)); // 強制轉換 Integer res = (Integer) t2.getObj(); System.out.println(res); }

執行,控制檯:
在這裡插入圖片描述
型別轉換錯誤,Float型別不能強制轉換成Integer型別,這是不允許的,但是編譯的時候並沒有報錯,這時候可以用泛型有效的解決這種向下轉型的型別安全問題。

2、定義泛型類

泛型類的定義很簡單,語法如下:

類名 <T>

使用泛型的好處就是不用再進行強制轉換了,也就不存在發生型別轉換錯誤。以下用例子說明。

定義一個泛型類T2:

/*
 * 定義泛型類
 * 型別用T表示
 */
public class T2<T> {

    // 這個obj沒有定義成具體型別
    private T obj;

    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }

}

測試:

    public static void main(String[] args) {
        // 傳入Boolean型別作為引數
        T2<Boolean> t0 = new T2<>();
        t0.setObj(true);
        Boolean b = t0.getObj();
        System.out.println(b);
        // 傳入Float型別作為引數
        T2<Float> t2 = new T2<>();
        t2.setObj(25.5f);
        Float f = t2.getObj();
        System.out.println(f);
    }

控制檯:
在這裡插入圖片描述

3、宣告多個型別

在定義泛型類的時候,可以同時宣告多個型別,語法如下:

類名 <型別1,型別2>

以下程式碼說明:

public class T3<Integer, Boolean> {

    private Boolean single;

    private Integer age;

    public Boolean getSingle() {
        return single;
    }

    public void setSingle(Boolean single) {
        this.single = single;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

}

測試:

    public static void main(String[] args) {
        T3<Integer, Boolean> t = new T3<>();
        t.setSingle(true);
        t.setAge(25);
        System.out.println("年齡:" + t.getAge());
        System.out.println("是單身嗎?" + t.getSingle());
    }

控制檯:
在這裡插入圖片描述

4、宣告陣列型別

在定義泛型的時候可以宣告為陣列型別,但是不能使用泛型機制來建立陣列例項。程式碼如下:

public class T4<T> {

    //這個陣列的型別為T
    private T[] arrays;

    public T[] getArrays() {
        return arrays;
    }

    public void setArrays(T[] arrays) {
        this.arrays = arrays;
    }

}

測試:

    public static void main(String[] args) {
        T4<Integer> t = new T4<>();
        Integer[] num = new Integer[] {1, 4, 3, 123, 45 };
        t.setArrays(num);
        System.out.println("陣列中的元素如下:");
        for (Integer i : t.getArrays()) {
            System.out.print(i + "\t");
        }
        System.out.println();
        System.out.println("--------------------------------");
        T4<String> t2 = new T4<>();
        String[] str = new String[] {"yan", "cheng", "zhi", "yun" };
        t2.setArrays(str);
        System.out.println("陣列中的元素如下:");
        for (String s : t2.getArrays()) {
            System.out.print(s + "\t");
        }
    }

控制檯:
在這裡插入圖片描述

5、宣告集合類的容器元素

可以使用K代表鍵,V代表值。如下:

public class T5<K, V> {

    public Map<K, V> map = new HashMap<>();

    // 設定put方法
    public void put(K k, V v) {
        map.put(k, v);
    }

    // 設定get方法
    public V get(K k) {
        return map.get(k);
    }

    public Map<K, V> getMap() {
        return map;
    }

    public void setMap(Map<K, V> map) {
        this.map = map;
    }

}

測試:

    public static void main(String[] args) {
        T5<String, Integer> t = new T5<>();
        for (int i = 1; i <= 5; i++) {
            t.put("第" + i + "個元素", i);
        }
        Set<Entry<String, Integer>> set = t.getMap().entrySet();
        for (Entry<String, Integer> entry : set) {
            System.out.println(entry.getKey() + "\t" + entry.getValue() + "\n");
        }
    }

控制檯:
在這裡插入圖片描述
事實上,這種是多餘的,因為Java的集合框架已經泛型化了,直接使用就行了,不用這麼麻煩的定義。

6、限制泛型可用型別

預設的可以使用任何的型別來例項化一個泛型物件,但是也可以做出限制,規定可以使用哪些型別來例項化物件。語法如下:

類名 <T extends 型別>

使用泛型限制以後,只有繼承了規定的型別或實現了這個介面的類才能作為泛型的引數,以下程式碼說明:

/*
 * 限制泛型引數型別
 */
public class T6<T extends List> {

    public static void main(String[] args) {
        // ArrayList實現了List介面,可以作為泛型引數
        T6<ArrayList> t = new T6<>();
        // LinkedList實現了List介面,可以作為泛型引數
        T6<LinkedList> t2 = new T6<>();
        // Vector實現了List介面,可以作為泛型引數
        T6<Vector> t3 = new T6<>();
        // 不接受Integer型別作為泛型引數
        // T6<Integer> t4 = new T6<>();
        // 不接受String型別作為泛型引數
        // T6<String> t4 = new T6<>();
    }

}

7、使用型別萬用字元

在泛型機制中,提供類的萬用字元?。萬用字元應用較少,有需求時才使用,不必要時可不用,採用泛型可滿足要求即可。

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("yan");
        list.add("cheng");
        list.add("zhi");
        List<?> list2 = list;
        System.out.println("list2集合大小為:" + list2.size());
        for (Object o : list2) {
            System.out.print(o.toString() + "\t");
        }
        System.out.println();
        List<Integer> list3 = new ArrayList<>();
        System.out.println("list3集合大小為:" + list3.size());
        //list2集合會被覆蓋掉
        list2 = list3;
        System.out.println("list2集合大小為:" + list2.size());
    }

在這裡插入圖片描述

8、泛型介面

也可以定義泛型的介面,像定義泛型類一樣。如下:

/*
 * 定義泛型介面
 */
public interface TestDao<T> {
    
    void save(T t);

}

介面的實現類:

public class TestDaoImpl<T> implements TestDao<T> {

    @Override
    public void save(T t) {
        // TODO Auto-generated method stub

    }

}