一,打破砂鍋問到底
泛型存在的意義?
泛型類表悬,泛型接口胜卤,泛型方法如何定義?
如何限定類型變量综膀?
泛型中使用的約束和局限性有哪些澳迫?
泛型類型的繼承規(guī)則是什么?
泛型中的通配符類型是什么剧劝?
如何獲取泛型的參數(shù)類型橄登?
虛擬機(jī)是如何實(shí)現(xiàn)泛型的?
在日常開發(fā)中是如何運(yùn)用泛型的讥此?
二拢锹,曉之以理動(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> T
genericAdd(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, <?>
指定了沒有限制的泛型類型
/**
* 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);
}
}