1. 程式人生 > 實用技巧 >IdentityServer 4 學習筆記 - 原始碼解讀

IdentityServer 4 學習筆記 - 原始碼解讀

泛型

1. 泛型概述

泛型:是JDK5中引入的特性,它提供了編譯時型別安全檢測機制,該機制允許在編譯時檢測到非法的型別

它的本質是引數化型別,也就是說所操作的資料型別被指定為一個引數

一提到引數,最熟悉的就是定義方法時有形參,然後呼叫此方法時傳遞實參。那麼引數化型別怎麼理解呢?

顧名思義,就是將型別由原來的具體的型別引數化,然後在使用/呼叫時傳入具體的型別

這種引數型別可以用在類、方法和介面中,分別被稱為泛型類、泛型方法、泛型介面

泛型定義格式:

  • <型別>:指定一種型別的格式。這裡的型別可以看成是形參

  • <型別1,型別2>:指定多種型別的格式,多種型別之間用逗號隔開。這裡的型別可以看成是實參,並且實參的型別只能是引用型別

泛型的好處:

  • 把執行時期的問題提前到了編譯期間

  • 避免了強制型別的轉換

1.2 泛型類

泛型類的定義格式:

  • 格式: 修飾符class 類名<型別>{}

  • 範例: public class Generic<T>{}

    此處T可以隨便寫為任意標識、常見的如T、E、K、V等形式的引數常用於表示泛型

學生類

public class Student {
    private String name;
​
    public String getName() {
        return name;
    }
​
    public void
setName(String name) { this.name = name; } }

教師類

public class Teacher {
    private Integer age;
​
    public Integer getAge() {
        return age;
    }
​
    public void setAge(Integer age) {
        this.age = age;
    }
}
​

泛型類

public class Generic<T> {
    private T t;
    
public T getT() { return t; } ​ public void setT(T t) { this.t = t; } }


測試類

public class GenericDemo {
    public static void main(String[] args) {
        Student s = new Student();
        s.setName("浪浪");
        System.out.println(s.getName());
​
        Teacher t = new Teacher();
        t.setAge(20);
        System.out.println(t.getAge());
        System.out.println("***************");
​
        Generic<String> g1 = new Generic<>();
        g1.setT("浪浪");
        System.out.println(g1.getT());
​
        Generic<Integer> g2 = new Generic<>();
        g2.setT(20);
        System.out.println(g2.getT());
    }
​
}

1.3泛型方法

泛型方法的定義格式:

  • 格式:修飾符<型別> 返回值型別方法名(型別 變數名){}

工具類

public class Generic {
    public void show(String s){
        System.out.println(s);
    }
    public void show(Integer i){
        System.out.println(i);
    }
    public void show(boolean t){
        System.out.println(t);
    }
​
}
*/
//泛型類改進
/*public class Generic<T>{
    public void show(T t){
        System.out.println(t);
    }
}*/
//泛型方法改進
public class Generic{
    public <T> void show(T t){
        System.out.println(t);
    }
}

測試類

public class GenericDemo {
    public static void main(String[] args) {
       /* Generic g = new Generic();
        g.show("浪浪");
        g.show(20);
        g.show(true);*//* Generic<String> g1 = new Generic<>();
        g1.show("浪浪");
        Generic<Integer> g2 = new Generic<>();
        g2.show(20);
        Generic<Boolean> g3 = new Generic<>();
        g3.show(true);*/
        Generic g = new Generic();
        g.show("浪浪");
        g.show(20);
        g.show(true);
    }
}

1.4 泛型介面

泛型介面的定義格式:

  • 格式:修飾符interface介面名<型別>{}

  • 範例:public interface Generic<T>{}

介面類

public interface Generic<T> {
    void show(T t);
}

實現類

public class GenericImpl<T> implements Generic<T> {
    @Override
    public void show(T t) {
        System.out.println(t);
    }
}
​

測試類

public class GenericDemo {
    public static void main(String[] args) {
        Generic<String> g1 = new GenericImpl<>();
        g1.show("浪浪");
        Generic<Integer> g2 = new GenericImpl<>();
        g2.show(20);
    }
}

1.5 型別萬用字元

為了表示各種泛型List的父類,可以使用型別萬用字元

  • 型別萬用字元:<?>

  • List<?>:表示元素型別未知的List,它的元素可以匹配任何的型別

  • 這種帶萬用字元的List僅代表它是各種泛型List的父類,並不能把元素新增到其中

如果我們不希望List<?>是任何泛型List的父類,只希望它代表某一類泛型List的父類,可以使用型別萬用字元的上限

  • 型別萬用字元上限:<? extends 型別>

  • List<? extends Number>: 它表示的型別是Number或者其子型別

除了可以指定型別萬用字元的上限,也可以指定型別萬用字元的下限

  • 型別萬用字元下限:<? super 型別>

  • List<? super Number>: 它表示的型別是Number或者其父型別

public class GenericDemo {
    public static void main(String[] args) {
        //型別萬用字元<?>
        List<?> list1 = new ArrayList<Object>();
        List<?> list2 = new ArrayList<String>();
        List<?> list3 = new ArrayList<Integer>();
        System.out.println("**************");

        //型別萬用字元的上限  <? extends 型別>
        //List<? extends Number> list4 = new ArrayList<Object>();//錯誤
        List<? extends Number> list5 = new ArrayList<Number>();
        List<? extends Number> list6 = new ArrayList<Integer>();
        System.out.println("*******************");

        //型別萬用字元下限 <? super 型別>
        List<? super Number> list7 = new ArrayList<Object>();
        List<? super Number> list8 = new ArrayList<Number>();
        //List<? super Number> list9 = new ArrayList<Integer>(); //錯誤
    }
}

1.6 可變引數

可變引數又稱引數個數可變,用作方法的形參出現,那麼方法引數個數就是可變的了

  • 格式:修飾符 返回值型別 方法名(資料型別... 變數名){}

  • 範例: public static int sum(int... a){}

可變引數注意事項

  • 這裡的變數其實是一個數組

  • 如果一個方法有多個引數,包含可變引數,可變引數要放在最後

測試類

public class ArgsDemo01 {
    public static void main(String[] args) {
        System.out.println(sum(10, 20));
        System.out.println(sum(10, 20, 30));
        System.out.println(sum(10, 20, 30, 40));

        System.out.println(sum(10,20,30,40,50));
        System.out.println(sum(10,20,30,40,50,60));
        System.out.println(sum(10,20,30,40,50,60,70));
        System.out.println(sum(10,20,30,40,50,60,70,80,90,100));

    }

    /*public static int sum(int... a){
        System.out.println(a);
        return 0;
    }*/
    //注意:一個方法如果有多個引數,可變引數要放在最後
    public static int sum(int... a){
        int sum = 0;
        for (int i : a){
            sum +=i;
        }
        return sum;
    }

    /*public static int sum(int a, int b) {
        return a + b;
    }

    public static int sum(int a, int b, int c) {
        return a + b + c;
    }

    public static int sum(int a, int b, int c, int d) {
        return a + b + c + d;
    }*/
}

1.7 可變引數的使用

Arrays工具類中有一個靜態方法:

  • public static <T> List<T> asList(T... a):返回由指定陣列支援的固定大小的列表

List介面中有一個靜態方法:

  • public static <E> List<E> of(E... elements):返回包含任意元素的不可變列表

Set介面中有一個靜態方法:

  • public static <E> Set<E> of(E... elements):返回一個包含任意數量元素的不可變集合