天天看点

泛型java 代码讲解_Java泛型详解

泛型java 代码讲解_Java泛型详解

2516326-5475e88a458a09e4.png

一,打破砂锅问到底

泛型存在的意义?

泛型类,泛型接口,泛型方法如何定义?

如何限定类型变量?

泛型中使用的约束和局限性有哪些?

泛型类型的继承规则是什么?

泛型中的通配符类型是什么?

如何获取泛型的参数类型?

虚拟机是如何实现泛型的?

在日常开发中是如何运用泛型的?

泛型java 代码讲解_Java泛型详解

Java泛型详解.png

二,晓之以理动之以码

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

泛型,即“参数化类型”。就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。

例如:GenericClass{}

一些常用的泛型类型变量:

E:元素(Element),多用于java集合框架

K:关键字(Key)

N:数字(Number)

T:类型(Type)

V:值(Value)

如果要实现不同类型的加法,每种类型都需要重载一个add方法

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

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 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;

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{}

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

public class GenericClass {

private T data;

public T getData() {

return data;

}

public void setData(T data) {

this.data = data;

}

public static void main(String[] args) {

GenericClass genericClass=new GenericClass<>();

genericClass.setData("Generic Class");

System.out.println(genericClass.getData());

}

}

3,泛型接口的使用

定义一个泛型接口:public interface GenericIntercace{}

public interface GenericIntercace {

T getData();

}

实现泛型接口方式一:public class ImplGenericInterface1 implements GenericIntercace

public class ImplGenericInterface1 implements GenericIntercace {

private T data;

private void setData(T data) {

this.data = data;

}

@Override

public T getData() {

return data;

}

public static void main(String[] args) {

ImplGenericInterface1 implGenericInterface1 = new ImplGenericInterface1<>();

implGenericInterface1.setData("Generic Interface1");

System.out.println(implGenericInterface1.getData());

}

}

实现泛型接口方式二:public class ImplGenericInterface2 implements GenericIntercace {}

public class ImplGenericInterface2 implements GenericIntercace {

@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 TgenericAdd(T a, T b) {}

public class GenericMethod1 {

private static int add(int a, int b) {

System.out.println(a + "+" + b + "=" + (a + b));

return a + b;

}

private static 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.genericAdd("a", "b");

}

}

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 {

public void show01(T t) {

System.out.println(t.toString());

}

public void show02(T t) {

System.out.println(t.toString());

}

public 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 genericClass = new GenericClass<>();

//泛型类在初始化时限制了参数类型

genericClass.show01(dog);

// genericClass.show01(fruit);

//泛型方法的参数类型在使用时指定

genericClass.show02(dog);

genericClass.show02(fruit);

genericClass.show03(animal);

genericClass.show03(dog);

genericClass.show03(fruit);

// genericClass.show03(animal);

}

}

5,限定泛型类型变量

1,对类的限定:public class TypeLimitForClass{}

2,对方法的限定:public static>T getMin(T a, T b) {}

public class TypeLimitForMethod {

// private static T getMin(T a, T b) {

// return (a.compareTo(b) > 0) ? a : b;

// }

public static > 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"));

}

}

public class TypeLimitForClass {

private T data;

public T getData() {

return data;

}

public void setData(T data) {

this.data = data;

}

public static void main(String[] args) {

ArrayList stringArrayList = new ArrayList<>();

stringArrayList.add("A");

stringArrayList.add("B");

ArrayList integerArrayList = new ArrayList<>();

integerArrayList.add(1);

integerArrayList.add(2);

integerArrayList.add(3);

TypeLimitForClass typeLimitForClass01 = new TypeLimitForClass<>();

typeLimitForClass01.setData(stringArrayList);

TypeLimitForClass typeLimitForClass02 = new TypeLimitForClass<>();

typeLimitForClass02.setData(integerArrayList);

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

}

public static > 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,不能捕获泛型类型限定的异常但可以将泛型限定的异常抛出

public class GenericRestrict1 {

static class NormalClass {

}

private T data;

public void setData() {

//this.data = new T();

}

// private static T result;

// private static T getResult() {

// return result;

// }

private static K getKey(K k) {

return k;

}

public static void main(String[] args) {

NormalClass normalClassA = new NormalClass();

NormalClass normalClassB = new NormalClass();

// GenericRestrict1 genericRestrictInt = new GenericRestrict1<>();

GenericRestrict1 genericRestrictInteger = new GenericRestrict1<>();

GenericRestrict1 genericRestrictString = new GenericRestrict1<>();

// if(genericRestrictInteger instanceof GenericRestrict1){

// return;

// }

// 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

GenericRestrict1[] genericRestrict1s;

// genericRestrict1s = new GenericRestrict1[10];

genericRestrict1s = new GenericRestrict1[10];

genericRestrict1s[0]=genericRestrictString;

}

}

public class GenericRestrict2 {

private class MyException extends Exception {

}

// private class MyGenericException extends Exception {

// }

//

// private class MyGenericThrowable extends Throwable {

// }

public void getException(T t) {

// try {

//

// } catch (T e) {

//

// }

}

public void getException(T t) throws T {

try {

} catch (Exception e) {

throw t;

}

}

}

7,泛型类型继承规则

1,对于泛型参数是继承关系的泛型类之间是没有继承关系的

2,泛型类可以继承其它泛型类,例如: public class ArrayList extends AbstractList

3,泛型类的继承关系在使用中同样会受到泛型类型的影响

public class GenericInherit {

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 void setData2(GenericInherit data2) {

}

public static void main(String[] args) {

// Son 继承自 Father

Father father = new Father();

Son son = new Son();

GenericInherit fatherGenericInherit = new GenericInherit<>();

GenericInherit sonGenericInherit = new GenericInherit<>();

SubGenericInherit fatherSubGenericInherit = new SubGenericInherit<>();

SubGenericInherit sonSubGenericInherit = new SubGenericInherit<>();

father = new Son();

// fatherGenericInherit=new GenericInherit();

fatherGenericInherit=new SubGenericInherit();

setData2(fatherGenericInherit);

// setData2(sonGenericInherit);

setData2(fatherSubGenericInherit);

// setData2(sonSubGenericInherit);

}

private static class SubGenericInherit extends GenericInherit {

}

8,通配符类型

1, extends Parent> 指定了泛型类型的上届

2, super Child> 指定了泛型类型的下届

3, > 指定了没有限制的泛型类型

泛型java 代码讲解_Java泛型详解

通配符测试类结构.png

public class GenericByWildcard {

private static void print(GenericClass fruitGenericClass) {

System.out.println(fruitGenericClass.getData().getColor());

}

private static void use() {

GenericClass fruitGenericClass = new GenericClass<>();

print(fruitGenericClass);

GenericClass orangeGenericClass = new GenericClass<>();

//类型不匹配,可以使用 extends Parent> 来解决

// print(orangeGenericClass);

}

private static void printExtends(GenericClass extends Fruit> genericClass) {

System.out.println(genericClass.getData().getColor());

}

public static void useExtend() {

GenericClass fruitGenericClass = new GenericClass<>();

printExtends(fruitGenericClass);

GenericClass orangeGenericClass = new GenericClass<>();

printExtends(orangeGenericClass);

GenericClass foodGenericClass = new GenericClass<>();

//Food是Fruit的父类,超过了泛型上届范围,类型不匹配

// printExtends(foodGenericClass);

//表示GenericClass的类型参数的上届是Fruit

GenericClass extends Fruit> extendFruitGenericClass = new GenericClass<>();

Apple apple = new Apple();

Fruit fruit = new Fruit();

// extendFruitGenericClass.setData(apple);

// extendFruitGenericClass.setData(fruit);

fruit = extendFruitGenericClass.getData();

}

public static void printSuper(GenericClass super Apple> genericClass) {

System.out.println(genericClass.getData());

}

public static void useSuper() {

GenericClass foodGenericClass = new GenericClass<>();

printSuper(foodGenericClass);

GenericClass fruitGenericClass = new GenericClass<>();

printSuper(fruitGenericClass);

GenericClass appleGenericClass = new GenericClass<>();

printSuper(appleGenericClass);

GenericClass hongFuShiAppleGenericClass = new GenericClass<>();

// HongFuShiApple 是Apple的子类,达不到泛型下届,类型不匹配

// printSuper(hongFuShiAppleGenericClass);

GenericClass orangeGenericClass = new GenericClass<>();

// Orange和Apple是兄弟关系,没有继承关系,类型不匹配

// printSuper(orangeGenericClass);

//表示GenericClass的类型参数的下界是Apple

GenericClass super Apple> supperAppleGenericClass = new GenericClass<>();

supperAppleGenericClass.setData(new Apple());

supperAppleGenericClass.setData(new HongFuShiApple());

// 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 foodGenericClass = new GenericClass<>();

printNonLimit(foodGenericClass);

GenericClass fruitGenericClass = new GenericClass<>();

printNonLimit(fruitGenericClass);

GenericClass 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]

Type[] getActualTypeArguments();

//返回当前class或interface声明的类型, 如List>返回List

Type getRawType();

//返回所属类型. 如,当前类型为O.I, 则返回O. 顶级类型将返回null

Type getOwnerType();

}

public class GenericType {

private T data;

public T getData() {

return data;

}

public void setData(T data) {

this.data = data;

}

public static void main(String[] args) {

GenericType genericType = new GenericType() {};

Type superclass = genericType.getClass().getGenericSuperclass();

//getActualTypeArguments 返回确切的泛型参数, 如Map返回[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 stringGenericClass=new GenericClass<>();

GenericClass integerGenericClass=new GenericClass<>();

C++中GenericClass和GenericClass是两个不同的类型

Java进行了类型擦除之后统一改为GenericClass

public class GenericTheory {

public static void main(String[] args) {

Map map = new HashMap<>();

map.put("Key", "Value");

System.out.println(map.get("Key"));

GenericClass genericClass = new GenericClass<>();

genericClass.put("Key", "Value");

System.out.println(genericClass.get("Key"));

}

public static class GenericClass {

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;

}

}

private class GenericClass2 {

}

private class GenericClass3 {

}

}

对应的字节码文件

public static void main(String[] args) {

Map map = new HashMap();

map.put("Key", "Value");

System.out.println((String)map.get("Key"));

GenericTheory.GenericClass 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

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

public class UserResponse extends BaseResponse {

private T data;

public T getData() {

return data;

}

public void setData(T data) {

this.data = data;

}

}

2,泛型+反射实现巧复用工具类

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 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());

}

public static void sortAnyList(List targetList, final String sortField, final boolean sortMode) {

if (targetList == null || targetList.size() < 2 || sortField == null || sortField.length() == 0) {

return;

}

Collections.sort(targetList, new Comparator() {

@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排序异常!");

e.printStackTrace();

}

return retVal;

}

});

}

}

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

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 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>() {}.getType();

List personList2 = gson.fromJson(json, personType);

System.out.println(personList2);

}

}