Java泛型詳解

一,打破砂鍋問到底

泛型存在的意義?
泛型類,泛型接口,泛型方法如何定義?
如何限定類型變量?
泛型中使用的約束和侷限性有哪些?
泛型類型的繼承規則是什麼?
泛型中的通配符類型是什麼?
如何獲取泛型的參數類型?
虛擬機是如何實現泛型的?
在日常開發中是如何運用泛型的?

Java泛型詳解.png

二,曉之以理動之以碼

1,泛型的定義以及存在意義

泛型,即“參數化類型”。就是將類型由原來的具體的類型參數化,類似於方法中的變量參數,此時類型也定義成參數形式(可以稱之爲類型形參),然後在使用/調用時傳入具體的類型(類型實參)。
例如:GenericClass<T>{}

一些常用的泛型類型變量:
E:元素(Element),多用於java集合框架
K:關鍵字(Key)
N:數字(Number)
T:類型(Type)
V:值(Value)

如果要實現不同類型的加法,每種類型都需要重載一個add方法

 

package com.jay.java.泛型.needGeneric;

/**
 * Author:Jay On 2019/5/9 16:06
 * <p>
 * Description: 爲什麼使用泛型
 */
public class NeedGeneric1 {

    private static int add(int a, int b) {
        System.out.println(a + "+" + b + "=" + (a + b));
        return a + b;
    }

    private static float add(float a, float b) {
        System.out.println(a + "+" + b + "=" + (a + b));
        return a + b;
    }

    private static double add(double a, double b) {
        System.out.println(a + "+" + b + "=" + (a + b));
        return a + b;
    }

    private static <T extends Number> double add(T a, T b) {
        System.out.println(a + "+" + b + "=" + (a.doubleValue() + b.doubleValue()));
        return a.doubleValue() + b.doubleValue();
    }

    public static void main(String[] args) {
        NeedGeneric1.add(1, 2);
        NeedGeneric1.add(1f, 2f);
        NeedGeneric1.add(1d, 2d);
        NeedGeneric1.add(Integer.valueOf(1), Integer.valueOf(2));
        NeedGeneric1.add(Float.valueOf(1), Float.valueOf(2));
        NeedGeneric1.add(Double.valueOf(1), Double.valueOf(2));
    }
}

取出集合元素時需要人爲的強制類型轉化到具體的目標類型,且很容易現“java.lang. ClassCast Exception”異常。

 

package com.jay.java.泛型.needGeneric;

import java.util.ArrayList;
import java.util.List;

/**
 * Author:Jay On 2019/5/9 16:23
 * <p>
 * Description: 爲什麼要使用泛型
 */
public class NeedGeneric2 {
    static class C{

    }
    public static void main(String[] args) {
        List list=new ArrayList();
        list.add("A");
        list.add("B");
        list.add(new C());
        list.add(100);
        //1.當我們將一個對象放入集合中,集合不會記住此對象的類型,當再次從集合中取出此對象時,改對象的編譯類型變成了Object類型,但其運行時類型任然爲其本身類型。
        //2.因此,//1處取出集合元素時需要人爲的強制類型轉化到具體的目標類型,且很容易出現“java.lang.ClassCastException”異常。
        for (int i = 0; i < list.size(); i++) {
//            System.out.println(list.get(i));
            String value= (String) list.get(i);
            System.out.println(value);
        }
    }
}

所以使用泛型的意義在於
1,適用於多種數據類型執行相同的代碼(代碼複用)
2, 泛型中的類型在使用時指定,不需要強制類型轉換(類型安全,編譯器會檢查類型)

2,泛型類的使用

定義一個泛型類:public class GenericClass<T>{}

 

package com.jay.java.泛型.DefineGeneric;

/**
 * Author:Jay On 2019/5/9 16:49
 * <p>
 * Description: 泛型類
 */
public class GenericClass<T> {
    private T data;

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public static void main(String[] args) {
        GenericClass<String> genericClass=new GenericClass<>();
        genericClass.setData("Generic Class");
        System.out.println(genericClass.getData());
    }
}

3,泛型接口的使用

定義一個泛型接口:public interface GenericIntercace<T>{}

 

/**
 * Author:Jay On 2019/5/9 16:57
 * <p>
 * Description: 泛型接口
 */
public interface GenericIntercace<T> {
     T getData();
}

實現泛型接口方式一:public class ImplGenericInterface1<T> implements GenericIntercace<T>

 

/**
 * Author:Jay On 2019/5/9 16:59
 * <p>
 * Description: 泛型接口實現類-泛型類實現方式
 */
public class ImplGenericInterface1<T> implements GenericIntercace<T> {
    private T data;

    private void setData(T data) {
        this.data = data;
    }

    @Override
    public T getData() {
        return data;
    }

    public static void main(String[] args) {
        ImplGenericInterface1<String> implGenericInterface1 = new ImplGenericInterface1<>();
        implGenericInterface1.setData("Generic Interface1");
        System.out.println(implGenericInterface1.getData());
    }
}

實現泛型接口方式二:public class ImplGenericInterface2 implements GenericIntercace<String> {}

 

/**
 * Author:Jay On 2019/5/9 17:01
 * <p>
 * Description: 泛型接口實現類-指定具體類型實現方式
 */
public class ImplGenericInterface2 implements GenericIntercace<String> {
    @Override
    public String getData() {
        return "Generic Interface2";
    }

    public static void main(String[] args) {
        ImplGenericInterface2 implGenericInterface2 = new ImplGenericInterface2();
        System.out.println(implGenericInterface2.getData());
    }
}

4,泛型方法的使用

定義一個泛型方法: private static<T> TgenericAdd(T a, T b) {}

 

/**
 * Author:Jay On 2019/5/10 10:46
 * <p>
 * Description: 泛型方法
 */
public class GenericMethod1 {
    private static int add(int a, int b) {
        System.out.println(a + "+" + b + "=" + (a + b));
        return a + b;
    }

    private static <T> T genericAdd(T a, T b) {
        System.out.println(a + "+" + b + "="+a+b);
        return a;
    }

    public static void main(String[] args) {
        GenericMethod1.add(1, 2);
        GenericMethod1.<String>genericAdd("a", "b");
    }
}

 

/**
 * Author:Jay On 2019/5/10 16:22
 * <p>
 * Description: 泛型方法
 */
public class GenericMethod3 {

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

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

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

    static class GenericClass<T> {

        public void show01(T t) {
            System.out.println(t.toString());
        }

        public <T> void show02(T t) {
            System.out.println(t.toString());
        }

        public <K> void show03(K k) {
            System.out.println(k.toString());
        }
    }

    public static void main(String[] args) {
        Animal animal = new Animal();
        Dog dog = new Dog();
        Fruit fruit = new Fruit();
        GenericClass<Animal> genericClass = new GenericClass<>();
        //泛型類在初始化時限制了參數類型
        genericClass.show01(dog);
//        genericClass.show01(fruit);

        //泛型方法的參數類型在使用時指定
        genericClass.show02(dog);
        genericClass.show02(fruit);

        genericClass.<Animal>show03(animal);
        genericClass.<Animal>show03(dog);
        genericClass.show03(fruit);
//        genericClass.<Dog>show03(animal);
    }
}

5,限定泛型類型變量

1,對類的限定:public class TypeLimitForClass<T extends List & Serializable>{}
2,對方法的限定:public static<T extends Comparable<T>>T getMin(T a, T b) {}

 

/**
 * Author:Jay On 2019/5/10 16:38
 * <p>
 * Description: 類型變量的限定-方法
 */
public class TypeLimitForMethod {

    /**
     * 計算最小值
     * 如果要實現這樣的功能就需要對泛型方法的類型做出限定
     */
//    private static <T> T getMin(T a, T b) {
//        return (a.compareTo(b) > 0) ? a : b;
//    }

    /**
     * 限定類型使用extends關鍵字指定
     * 可以使類,接口,類放在前面接口放在後面用&符號分割
     * 例如:<T extends ArrayList & Comparable<T> & Serializable>
     */
    public static <T extends Comparable<T>> T getMin(T a, T b) {
        return (a.compareTo(b) < 0) ? a : b;
    }

    public static void main(String[] args) {
        System.out.println(TypeLimitForMethod.getMin(2, 4));
        System.out.println(TypeLimitForMethod.getMin("a", "r"));
    }
}

 

/**
 * Author:Jay On 2019/5/10 17:02
 * <p>
 * Description: 類型變量的限定-類
 */
public class TypeLimitForClass<T extends List & Serializable> {
    private T data;

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public static void main(String[] args) {
        ArrayList<String> stringArrayList = new ArrayList<>();
        stringArrayList.add("A");
        stringArrayList.add("B");
        ArrayList<Integer> integerArrayList = new ArrayList<>();
        integerArrayList.add(1);
        integerArrayList.add(2);
        integerArrayList.add(3);
        TypeLimitForClass<ArrayList> typeLimitForClass01 = new TypeLimitForClass<>();
        typeLimitForClass01.setData(stringArrayList);
        TypeLimitForClass<ArrayList> typeLimitForClass02 = new TypeLimitForClass<>();
        typeLimitForClass02.setData(integerArrayList);

        System.out.println(getMinListSize(typeLimitForClass01.getData().size(), typeLimitForClass02.getData().size()));

    }

    public static <T extends Comparable<T>> T getMinListSize(T a, T b) {
        return (a.compareTo(b) < 0) ? a : b;
    }

6,泛型中的約束和侷限性

1,不能實例化泛型類
2,靜態變量或方法不能引用泛型類型變量,但是靜態泛型方法是可以的
3,基本類型無法作爲泛型類型
4,無法使用instanceof關鍵字或==判斷泛型類的類型
5,泛型類的原生類型與所傳遞的泛型無關,無論傳遞什麼類型,原生類是一樣的
6,泛型數組可以聲明但無法實例化
7,泛型類不能繼承Exception或者Throwable
8,不能捕獲泛型類型限定的異常但可以將泛型限定的異常拋出

 

/**
 * Author:Jay On 2019/5/10 17:41
 * <p>
 * Description: 泛型的約束和侷限性
 */
public class GenericRestrict1<T> {
    static class NormalClass {

    }

    private T data;

    /**
     * 不能實例化泛型類
     * Type parameter 'T' cannot be instantiated directly
     */
    public void setData() {
        //this.data = new T();
    }

    /**
     * 靜態變量或方法不能引用泛型類型變量
     * 'com.jay.java.泛型.restrict.GenericRestrict1.this' cannot be referenced from a static context
     */
//    private static T result;

//    private static T getResult() {
//        return result;
//    }

    /**
     * 靜態泛型方法是可以的
     */
    private static <K> K getKey(K k) {
        return k;
    }

    public static void main(String[] args) {
        NormalClass normalClassA = new NormalClass();
        NormalClass normalClassB = new NormalClass();
        /**
         * 基本類型無法作爲泛型類型
         */
//        GenericRestrict1<int> genericRestrictInt = new GenericRestrict1<>();
        GenericRestrict1<Integer> genericRestrictInteger = new GenericRestrict1<>();
        GenericRestrict1<String> genericRestrictString = new GenericRestrict1<>();
        /**
         * 無法使用instanceof關鍵字判斷泛型類的類型
         * Illegal generic type for instanceof
         */
//        if(genericRestrictInteger instanceof GenericRestrict1<Integer>){
//            return;
//        }

        /**
         * 無法使用“==”判斷兩個泛型類的實例
         * Operator '==' cannot be applied to this two instance
         */
//        if (genericRestrictInteger == genericRestrictString) {
//            return;
//        }

        /**
         * 泛型類的原生類型與所傳遞的泛型無關,無論傳遞什麼類型,原生類是一樣的
         */
        System.out.println(normalClassA == normalClassB);//false
        System.out.println(genericRestrictInteger == genericRestrictInteger);//
        System.out.println(genericRestrictInteger.getClass() == genericRestrictString.getClass()); //true
        System.out.println(genericRestrictInteger.getClass());//com.jay.java.泛型.restrict.GenericRestrict1
        System.out.println(genericRestrictString.getClass());//com.jay.java.泛型.restrict.GenericRestrict1

        /**
         * 泛型數組可以聲明但無法實例化
         * Generic array creation
         */
        GenericRestrict1<String>[] genericRestrict1s;
//        genericRestrict1s = new GenericRestrict1<String>[10];
        genericRestrict1s = new GenericRestrict1[10];
        genericRestrict1s[0]=genericRestrictString;
    }

}

 

/**
 * Author:Jay On 2019/5/10 18:45
 * <p>
 * Description: 泛型和異常
 */
public class GenericRestrict2 {

    private class MyException extends Exception {
    }

    /**
     * 泛型類不能繼承Exception或者Throwable
     * Generic class may not extend 'java.lang.Throwable'
     */
//    private class MyGenericException<T> extends Exception {
//    }
//
//    private class MyGenericThrowable<T> extends Throwable {
//    }

    /**
     * 不能捕獲泛型類型限定的異常
     * Cannot catch type parameters
     */
    public <T extends Exception> void getException(T t) {
//        try {
//
//        } catch (T e) {
//
//        }
    }

    /**
     *可以將泛型限定的異常拋出
     */
    public <T extends Throwable> void getException(T t) throws T {
        try {

        } catch (Exception e) {
            throw t;
        }
    }
}

7,泛型類型繼承規則

1,對於泛型參數是繼承關係的泛型類之間是沒有繼承關係的
2,泛型類可以繼承其它泛型類,例如: public class ArrayList<E> extends AbstractList<E>
3,泛型類的繼承關係在使用中同樣會受到泛型類型的影響

 

/**
 * Author:Jay On 2019/5/10 19:13
 * <p>
 * Description: 泛型繼承規則測試類
 */
public class GenericInherit<T> {
    private T data1;
    private T data2;

    public T getData1() {
        return data1;
    }

    public void setData1(T data1) {
        this.data1 = data1;
    }

    public T getData2() {
        return data2;
    }

    public void setData2(T data2) {
        this.data2 = data2;
    }

    public static <V> void setData2(GenericInherit<Father> data2) {

    }

    public static void main(String[] args) {
//        Son 繼承自 Father
        Father father = new Father();
        Son son = new Son();
        GenericInherit<Father> fatherGenericInherit = new GenericInherit<>();
        GenericInherit<Son> sonGenericInherit = new GenericInherit<>();
        SubGenericInherit<Father> fatherSubGenericInherit = new SubGenericInherit<>();
        SubGenericInherit<Son> sonSubGenericInherit = new SubGenericInherit<>();

        /**
         * 對於傳遞的泛型類型是繼承關係的泛型類之間是沒有繼承關係的
         * GenericInherit<Father> 與GenericInherit<Son> 沒有繼承關係
         * Incompatible types.
         */
        father = new Son();
//        fatherGenericInherit=new GenericInherit<Son>();

        /**
         * 泛型類可以繼承其它泛型類,例如: public class ArrayList<E> extends AbstractList<E>
         */
        fatherGenericInherit=new SubGenericInherit<Father>();

        /**
         *泛型類的繼承關係在使用中同樣會受到泛型類型的影響
         */
        setData2(fatherGenericInherit);
//        setData2(sonGenericInherit);
        setData2(fatherSubGenericInherit);
//        setData2(sonSubGenericInherit);

    }

    private static class SubGenericInherit<T> extends GenericInherit<T> {

    }

8,通配符類型

1,<? extends Parent> 指定了泛型類型的上屆
2,<? super Child> 指定了泛型類型的下屆
3, <?> 指定了沒有限制的泛型類型

通配符測試類結構.png

 

/**
 * Author:Jay On 2019/5/10 19:51
 * <p>
 * Description: 泛型通配符測試類
 */
public class GenericByWildcard {
    private static void print(GenericClass<Fruit> fruitGenericClass) {
        System.out.println(fruitGenericClass.getData().getColor());
    }

    private static void use() {
        GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
        print(fruitGenericClass);
        GenericClass<Orange> orangeGenericClass = new GenericClass<>();
        //類型不匹配,可以使用<? extends Parent> 來解決
//        print(orangeGenericClass);
    }

    /**
     * <? extends Parent> 指定了泛型類型的上屆
     */
    private static void printExtends(GenericClass<? extends Fruit> genericClass) {
        System.out.println(genericClass.getData().getColor());
    }

    public static void useExtend() {
        GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
        printExtends(fruitGenericClass);
        GenericClass<Orange> orangeGenericClass = new GenericClass<>();
        printExtends(orangeGenericClass);

        GenericClass<Food> foodGenericClass = new GenericClass<>();
        //Food是Fruit的父類,超過了泛型上屆範圍,類型不匹配
//        printExtends(foodGenericClass);

        //表示GenericClass的類型參數的上屆是Fruit
        GenericClass<? extends Fruit> extendFruitGenericClass = new GenericClass<>();
        Apple apple = new Apple();
        Fruit fruit = new Fruit();
        /*
         * 道理很簡單,? extends X  表示類型的上界,類型參數是X的子類,那麼可以肯定的說,
         * get方法返回的一定是個X(不管是X或者X的子類)編譯器是可以確定知道的。
         * 但是set方法只知道傳入的是個X,至於具體是X的那個子類,不知道。
         * 總結:主要用於安全地訪問數據,可以訪問X及其子類型,並且不能寫入非null的數據。
         */
//        extendFruitGenericClass.setData(apple);
//        extendFruitGenericClass.setData(fruit);

        fruit = extendFruitGenericClass.getData();

    }

    /**
     * <? super Child> 指定了泛型類型的下屆
     */
    public static void printSuper(GenericClass<? super Apple> genericClass) {
        System.out.println(genericClass.getData());
    }

    public static void useSuper() {
        GenericClass<Food> foodGenericClass = new GenericClass<>();
        printSuper(foodGenericClass);

        GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
        printSuper(fruitGenericClass);

        GenericClass<Apple> appleGenericClass = new GenericClass<>();
        printSuper(appleGenericClass);

        GenericClass<HongFuShiApple> hongFuShiAppleGenericClass = new GenericClass<>();
        // HongFuShiApple 是Apple的子類,達不到泛型下屆,類型不匹配
//        printSuper(hongFuShiAppleGenericClass);

        GenericClass<Orange> orangeGenericClass = new GenericClass<>();
        // Orange和Apple是兄弟關係,沒有繼承關係,類型不匹配
//        printSuper(orangeGenericClass);

        //表示GenericClass的類型參數的下界是Apple
        GenericClass<? super Apple> supperAppleGenericClass = new GenericClass<>();
        supperAppleGenericClass.setData(new Apple());
        supperAppleGenericClass.setData(new HongFuShiApple());
        /*
         * ? super  X  表示類型的下界,類型參數是X的超類(包括X本身),
         * 那麼可以肯定的說,get方法返回的一定是個X的超類,那麼到底是哪個超類?不知道,
         * 但是可以肯定的說,Object一定是它的超類,所以get方法返回Object。
         * 編譯器是可以確定知道的。對於set方法來說,編譯器不知道它需要的確切類型,但是X和X的子類可以安全的轉型爲X。
         * 總結:主要用於安全地寫入數據,可以寫入X及其子類型。
         */
//        supperAppleGenericClass.setData(new Fruit());

        //get方法只會返回一個Object類型的值。
        Object data = supperAppleGenericClass.getData();
    }

    /**
     * <?> 指定了沒有限定的通配符
     */
    public static void printNonLimit(GenericClass<?> genericClass) {
        System.out.println(genericClass.getData());
    }

    public static void useNonLimit() {
        GenericClass<Food> foodGenericClass = new GenericClass<>();
        printNonLimit(foodGenericClass);
        GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
        printNonLimit(fruitGenericClass);
        GenericClass<Apple> appleGenericClass = new GenericClass<>();
        printNonLimit(appleGenericClass);

        GenericClass<?> genericClass = new GenericClass<>();
        //setData 方法不能被調用, 甚至不能用 Object 調用;
//        genericClass.setData(foodGenericClass);
//        genericClass.setData(new Object());
        //返回值只能賦給 Object
        Object object = genericClass.getData();

    }

}

9,獲取泛型的參數類型

Type是什麼
這裏的Type指java.lang.reflect.Type, 是Java中所有類型的公共高級接口, 代表了Java中的所有類型. Type體系中類型的包括:數組類型(GenericArrayType)、參數化類型(ParameterizedType)、類型變量(TypeVariable)、通配符類型(WildcardType)、原始類型(Class)、基本類型(Class), 以上這些類型都實現Type接口.

參數化類型,就是我們平常所用到的泛型List、Map;
數組類型,並不是我們工作中所使用的數組String[] 、byte[],而是帶有泛型的數組,即T[] ;
通配符類型, 指的是<?>, <? extends T>等等
原始類型, 不僅僅包含我們平常所指的類,還包括枚舉、數組、註解等;
基本類型, 也就是我們所說的java的基本類型,即int,float,double等

 

public interface ParameterizedType extends Type {
    // 返回確切的泛型參數, 如Map<String, Integer>返回[String, Integer]
    Type[] getActualTypeArguments();
    
    //返回當前class或interface聲明的類型, 如List<?>返回List
    Type getRawType();
    
    //返回所屬類型. 如,當前類型爲O<T>.I<S>, 則返回O<T>. 頂級類型將返回null 
    Type getOwnerType();
}

 

/**
 * Author:Jay On 2019/5/11 22:41
 * <p>
 * Description: 獲取泛型類型測試類
 */
public class GenericType<T> {
    private T data;

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public static void main(String[] args) {
        GenericType<String> genericType = new GenericType<String>() {};
        Type superclass = genericType.getClass().getGenericSuperclass();
        //getActualTypeArguments 返回確切的泛型參數, 如Map<String, Integer>返回[String, Integer]
        Type type = ((ParameterizedType) superclass).getActualTypeArguments()[0]; 
        System.out.println(type);//class java.lang.String
    }
}

10,虛擬機是如何實現泛型的

Java泛型是Java1.5之後才引入的,爲了向下兼容。Java採用了C++完全不同的實現思想。Java中的泛型更多的看起來像是編譯期用的
Java中泛型在運行期是不可見的,會被擦除爲它的上級類型。如果是沒有限定的泛型參數類型,就會被替換爲Object.

 

GenericClass<String> stringGenericClass=new GenericClass<>();
GenericClass<Integer> integerGenericClass=new GenericClass<>();

C++中GenericClass<String>和GenericClass<Integer>是兩個不同的類型
Java進行了類型擦除之後統一改爲GenericClass<Object>

 

/**
 * Author:Jay On 2019/5/11 16:11
 * <p>
 * Description:泛型原理測試類
 */
public class GenericTheory {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("Key", "Value");
        System.out.println(map.get("Key"));
        GenericClass<String, String> genericClass = new GenericClass<>();
        genericClass.put("Key", "Value");
        System.out.println(genericClass.get("Key"));
    }

    public static class GenericClass<K, V> {
        private K key;
        private V value;

        public void put(K key, V value) {
            this.key = key;
            this.value = value;
        }

        public V get(V key) {
            return value;
        }
    }

    /**
     * 類型擦除後GenericClass2<Object>
     * @param <T>
     */
    private class GenericClass2<T> {

    }

    /**
     * 類型擦除後GenericClass3<ArrayList>
     * 當使用到Serializable時會將相應代碼強制轉換爲Serializable
     * @param <T>
     */
    private class GenericClass3<T extends ArrayList & Serializable> {

    }
}

對應的字節碼文件

 

 public static void main(String[] args) {
        Map<String, String> map = new HashMap();
        map.put("Key", "Value");
        System.out.println((String)map.get("Key"));
        GenericTheory.GenericClass<String, String> genericClass = new GenericTheory.GenericClass();
        genericClass.put("Key", "Value");
        System.out.println((String)genericClass.get("Key"));
    }

三,學以致用

1,泛型解析JSON數據封裝

api返回的json數據

 

{
    "code":200,
    "msg":"成功",
    "data":{
        "name":"Jay",
        "email":"10086"
    }
}

BaseResponse .java

 

/**
 * Author:Jay On 2019/5/11 20:48
 * <p>
 * Description: 接口數據接收基類
 */
public class BaseResponse {

    private int code;
    private String msg;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

UserResponse.java

 

/**
 * Author:Jay On 2019/5/11 20:49
 * <p>
 * Description: 用戶信息接口實體類
 */
public class UserResponse<T> extends BaseResponse {
    private T data;

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

2,泛型+反射實現巧複用工具類

 

/**
 * Author:Jay On 2019/5/11 21:05
 * <p>
 * Description: 泛型相關的工具類
 */
public class GenericUtils {

    public static class Movie {
        private String name;
        private Date time;

        public String getName() {
            return name;
        }

        public Date getTime() {
            return time;
        }

        public Movie(String name, Date time) {
            this.name = name;
            this.time = time;
        }

        @Override
        public String toString() {
            return "Movie{" + "name='" + name + '\'' + ", time=" + time + '}';
        }
    }

    public static void main(String[] args) {
        List<Movie> movieList = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            movieList.add(new Movie("movie" + i, new Date()));
        }
        System.out.println("排序前:" + movieList.toString());

        GenericUtils.sortAnyList(movieList, "name", true);
        System.out.println("按name正序排:" + movieList.toString());

        GenericUtils.sortAnyList(movieList, "name", false);
        System.out.println("按name逆序排:" + movieList.toString());
    }

    /**
     * 對任意集合的排序方法
     * @param targetList 要排序的實體類List集合
     * @param sortField  排序字段
     * @param sortMode   true正序,false逆序
     */
    public static <T> void sortAnyList(List<T> targetList, final String sortField, final boolean sortMode) {
        if (targetList == null || targetList.size() < 2 || sortField == null || sortField.length() == 0) {
            return;
        }
        Collections.sort(targetList, new Comparator<Object>() {
            @Override
            public int compare(Object obj1, Object obj2) {
                int retVal = 0;
                try {
                    // 獲取getXxx()方法名稱
                    String methodStr = "get" + sortField.substring(0, 1).toUpperCase() + sortField.substring(1);
                    Method method1 = ((T) obj1).getClass().getMethod(methodStr, null);
                    Method method2 = ((T) obj2).getClass().getMethod(methodStr, null);
                    if (sortMode) {
                        retVal = method1.invoke(((T) obj1), null).toString().compareTo(method2.invoke(((T) obj2), null).toString());
                    } else {
                        retVal = method2.invoke(((T) obj2), null).toString().compareTo(method1.invoke(((T) obj1), null).toString());
                    }
                } catch (Exception e) {
                    System.out.println("List<" + ((T) obj1).getClass().getName() + ">排序異常!");
                    e.printStackTrace();
                }
                return retVal;
            }
        });
    }
}

3,Gson庫中的泛型的使用-TypeToken

 

/**
 * Author:Jay On 2019/5/11 22:11
 * <p>
 * Description: Gson庫中的泛型使用
 */
public class GsonGeneric {
    public static class Person {
        private String name;
        private int age;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

    public static void main(String[] args) {
        Gson gson = new Gson();
        List<Person> personList = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            personList.add(new Person("name" + i, 18 + i));
        }
        // Serialization
        String json = gson.toJson(personList);
        System.out.println(json);
        // Deserialization
        Type personType = new TypeToken<List<Person>>() {}.getType();
        List<Person> personList2 = gson.fromJson(json, personType);
        System.out.println(personList2);
    }
}



作者:JayDroid
鏈接:https://www.jianshu.com/p/986f732ed2f1
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

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