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, <?> 指定了没有限制的泛型类型

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

最新文章

  1. MongoDB和Redis-NoSQL数据库-文档型-内存型
  2. Android系统启动过程
  3. 自定义泛型N维空间数组
  4. java变量作用域
  5. Java基础知识强化之IO流笔记57:数据输入输出流(操作基本数据类型)
  6. 检测到有潜在危险的Request.Form值
  7. o(n)解决问题:调整数组顺序是奇数位于偶数的前面
  8. libev中timer时间事件监控器
  9. xmppserver
  10. em单位使用小结
  11. IDEA使用有道翻译插件
  12. 前端开发必备之chrome插件
  13. JavaScript正则表达式模式匹配(1)——基本字符匹配
  14. Delphi 开发手机 App 与其他工具之间的比较分析
  15. Spring核心之IOC
  16. 谈一谈 MPU6050 姿态融合(转)
  17. selenium配置文件定位元素
  18. python 05集合
  19. 禁止textarea拉伸
  20. 树状数组训练题1:弱弱的战壕(vijos1066)

热门文章

  1. Python爬虫下载酷狗音乐
  2. Hive——基本DDL语句
  3. Hive——简介
  4. python + pytest基本使用方法(拓展库)
  5. @classmethod和@staticmethod修饰符
  6. 鸿蒙轻内核定时器Swtmr:不受硬件和数量限制,满足用户需求
  7. jvm源码解读--06 Method 方法解析
  8. jvm源码解读--01 jvm加载java/lang/object过程
  9. etcd raft 处理流程图系列2-transport
  10. 洛谷P1377题解