2020国产成人精品视频,性做久久久久久久久,亚洲国产成人久久综合一区,亚洲影院天堂中文av色

分享

Java泛型詳解

 sxw6wduc8b7bn5 2020-02-14
2516326-5475e88a458a09e4.png

一,打破砂鍋問到底

泛型存在的意義?
泛型類,泛型接口,泛型方法如何定義?
如何限定類型變量?
泛型中使用的約束和局限性有哪些?
泛型類型的繼承規(guī)則是什么?
泛型中的通配符類型是什么?
如何獲取泛型的參數(shù)類型?
虛擬機(jī)是如何實(shí)現(xiàn)泛型的?
在日常開發(fā)中是如何運(yùn)用泛型的?

Java泛型詳解.png

二,曉之以理動(dòng)之以碼

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

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

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

如果要實(shí)現(xiàn)不同類型的加法,每種類型都需要重載一個(gè)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));
    }
}

取出集合元素時(shí)需要人為的強(qiáng)制類型轉(zhuǎn)化到具體的目標(biāo)類型,且很容易現(xiàn)“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.當(dāng)我們將一個(gè)對(duì)象放入集合中,集合不會(huì)記住此對(duì)象的類型,當(dāng)再次從集合中取出此對(duì)象時(shí),改對(duì)象的編譯類型變成了Object類型,但其運(yùn)行時(shí)類型任然為其本身類型。
        //2.因此,//1處取出集合元素時(shí)需要人為的強(qiáng)制類型轉(zhuǎn)化到具體的目標(biāo)類型,且很容易出現(xiàn)“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,適用于多種數(shù)據(jù)類型執(zhí)行相同的代碼(代碼復(fù)用)
2, 泛型中的類型在使用時(shí)指定,不需要強(qiáng)制類型轉(zhuǎn)換(類型安全,編譯器會(huì)檢查類型)

2,泛型類的使用

定義一個(gè)泛型類: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,泛型接口的使用

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

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

實(shí)現(xiàn)泛型接口方式一:public class ImplGenericInterface1<T> implements GenericIntercace<T>

/**
 * Author:Jay On 2019/5/9 16:59
 * <p>
 * Description: 泛型接口實(shí)現(xiàn)類-泛型類實(shí)現(xiàn)方式
 */
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());
    }
}

實(shí)現(xiàn)泛型接口方式二:public class ImplGenericInterface2 implements GenericIntercace<String> {}

/**
 * Author:Jay On 2019/5/9 17:01
 * <p>
 * Description: 泛型接口實(shí)現(xiàn)類-指定具體類型實(shí)現(xiàn)方式
 */
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,泛型方法的使用

定義一個(gè)泛型方法: 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<>();
        //泛型類在初始化時(shí)限制了參數(shù)類型
        genericClass.show01(dog);
//        genericClass.show01(fruit);

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

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

5,限定泛型類型變量

1,對(duì)類的限定:public class TypeLimitForClass<T extends List & Serializable>{}
2,對(duì)方法的限定: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 {

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

    /**
     * 限定類型使用extends關(guān)鍵字指定
     * 可以使類,接口,類放在前面接口放在后面用&符號(hào)分割
     * 例如:<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,不能實(shí)例化泛型類
2,靜態(tài)變量或方法不能引用泛型類型變量,但是靜態(tài)泛型方法是可以的
3,基本類型無法作為泛型類型
4,無法使用instanceof關(guān)鍵字或==判斷泛型類的類型
5,泛型類的原生類型與所傳遞的泛型無關(guān),無論傳遞什么類型,原生類是一樣的
6,泛型數(shù)組可以聲明但無法實(shí)例化
7,泛型類不能繼承Exception或者Throwable
8,不能捕獲泛型類型限定的異常但可以將泛型限定的異常拋出

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

    }

    private T data;

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

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

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

    /**
     * 靜態(tài)泛型方法是可以的
     */
    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關(guān)鍵字判斷泛型類的類型
         * Illegal generic type for instanceof
         */
//        if(genericRestrictInteger instanceof GenericRestrict1<Integer>){
//            return;
//        }

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

        /**
         * 泛型類的原生類型與所傳遞的泛型無關(guān),無論傳遞什么類型,原生類是一樣的
         */
        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

        /**
         * 泛型數(shù)組可以聲明但無法實(shí)例化
         * 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,泛型類型繼承規(guī)則

1,對(duì)于泛型參數(shù)是繼承關(guān)系的泛型類之間是沒有繼承關(guān)系的
2,泛型類可以繼承其它泛型類,例如: public class ArrayList<E> extends AbstractList<E>
3,泛型類的繼承關(guān)系在使用中同樣會(huì)受到泛型類型的影響

/**
 * Author:Jay On 2019/5/10 19:13
 * <p>
 * Description: 泛型繼承規(guī)則測(cè)試類
 */
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<>();

        /**
         * 對(duì)于傳遞的泛型類型是繼承關(guān)系的泛型類之間是沒有繼承關(guān)系的
         * GenericInherit<Father> 與GenericInherit<Son> 沒有繼承關(guān)系
         * Incompatible types.
         */
        father = new Son();
//        fatherGenericInherit=new GenericInherit<Son>();

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

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

    }

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

    }

8,通配符類型

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

通配符測(cè)試類結(jié)構(gòu).png
/**
 * Author:Jay On 2019/5/10 19:51
 * <p>
 * Description: 泛型通配符測(cè)試類
 */
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的類型參數(shù)的上屆是Fruit
        GenericClass<? extends Fruit> extendFruitGenericClass = new GenericClass<>();
        Apple apple = new Apple();
        Fruit fruit = new Fruit();
        /*
         * 道理很簡(jiǎn)單,? extends X  表示類型的上界,類型參數(shù)是X的子類,那么可以肯定的說,
         * get方法返回的一定是個(gè)X(不管是X或者X的子類)編譯器是可以確定知道的。
         * 但是set方法只知道傳入的是個(gè)X,至于具體是X的那個(gè)子類,不知道。
         * 總結(jié):主要用于安全地訪問數(shù)據(jù),可以訪問X及其子類型,并且不能寫入非null的數(shù)據(jù)。
         */
//        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的子類,達(dá)不到泛型下屆,類型不匹配
//        printSuper(hongFuShiAppleGenericClass);

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

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

        //get方法只會(huì)返回一個(gè)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 方法不能被調(diào)用, 甚至不能用 Object 調(diào)用;
//        genericClass.setData(foodGenericClass);
//        genericClass.setData(new Object());
        //返回值只能賦給 Object
        Object object = genericClass.getData();

    }

}

9,獲取泛型的參數(shù)類型

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

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

public interface ParameterizedType extends Type {
    // 返回確切的泛型參數(shù), 如Map<String, Integer>返回[String, Integer]
    Type[] getActualTypeArguments();
    
    //返回當(dāng)前class或interface聲明的類型, 如List<?>返回List
    Type getRawType();
    
    //返回所屬類型. 如,當(dāng)前類型為O<T>.I<S>, 則返回O<T>. 頂級(jí)類型將返回null 
    Type getOwnerType();
}
/**
 * Author:Jay On 2019/5/11 22:41
 * <p>
 * Description: 獲取泛型類型測(cè)試類
 */
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 返回確切的泛型參數(shù), 如Map<String, Integer>返回[String, Integer]
        Type type = ((ParameterizedType) superclass).getActualTypeArguments()[0]; 
        System.out.println(type);//class java.lang.String
    }
}

10,虛擬機(jī)是如何實(shí)現(xiàn)泛型的

Java泛型是Java1.5之后才引入的,為了向下兼容。Java采用了C++完全不同的實(shí)現(xiàn)思想。Java中的泛型更多的看起來像是編譯期用的
Java中泛型在運(yùn)行期是不可見的,會(huì)被擦除為它的上級(jí)類型。如果是沒有限定的泛型參數(shù)類型,就會(huì)被替換為Object.

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

C++中GenericClass<String>和GenericClass<Integer>是兩個(gè)不同的類型
Java進(jìn)行了類型擦除之后統(tǒng)一改為GenericClass<Object>

/**
 * Author:Jay On 2019/5/11 16:11
 * <p>
 * Description:泛型原理測(cè)試類
 */
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>
     * 當(dāng)使用到Serializable時(shí)會(huì)將相應(yīng)代碼強(qiáng)制轉(zhuǎn)換為Serializable
     * @param <T>
     */
    private class GenericClass3<T extends ArrayList & Serializable> {

    }
}

對(duì)應(yīng)的字節(jié)碼文件

 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"));
    }

三,學(xué)以致用

1,泛型解析JSON數(shù)據(jù)封裝

api返回的json數(shù)據(jù)

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

BaseResponse .java

/**
 * Author:Jay On 2019/5/11 20:48
 * <p>
 * Description: 接口數(shù)據(jù)接收基類
 */
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: 用戶信息接口實(shí)體類
 */
public class UserResponse<T> extends BaseResponse {
    private T data;

    public T getData() {
        return data;
    }

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

2,泛型+反射實(shí)現(xiàn)巧復(fù)用工具類

/**
 * Author:Jay On 2019/5/11 21:05
 * <p>
 * Description: 泛型相關(guān)的工具類
 */
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());
    }

    /**
     * 對(duì)任意集合的排序方法
     * @param targetList 要排序的實(shí)體類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);
    }
}

測(cè)試代碼

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多