泛型的英文名Generic,java5以后,引入参数化类型(parameterized type)概念,允许在创建集合时指定集合元素的类型。Java 的 参 数 化 类 型 被 称 为 泛 型(Generic)。
代码示例:
public static void main(String[] args) {
// 指定类型为String
List<String> list = new ArrayList<>();
list.add("dsf");
// 类型不符,报错
list.add(1);
}
public class Pair<T> {
private T first;
private T second;
public Pair() {
}
public Pair(T min, T max) {
this.first = min;
this.second = max;
}
public T getFirst() {
return first;
}
public void setFirst(T first) {
this.first = first;
}
public T getSecond() {
return second;
}
public void setSecond(T second) {
this.second = second;
}
}
类型变量T用<>括起来,使用大写形式。在java中,使用E表示集合中的元素,K和V表示键和值,T(U,S)表示任意类型。
使用示例:
public class ArrayAlg {
public static Pair<String> minmax(String[] arr) {
if (arr == null || arr.length == 0) {
return null;
}
String min = arr[0];
String max = arr[0];
for (int i = 0, length = arr.length; i < length; i++) {
if (min.compareTo(arr[i]) > 0) {
min = arr[i];
}
if (max.compareTo(arr[i]) < 0) {
max = arr[i];
}
}
return new Pair<>(min, max);
}
}
public static <T> T getMiddle(T... arr) {
return arr[arr.length / 2];
}
使用示例:
public static void main(String[] args) {
String sdaf = ArrayAlg.getMiddle("123", "sdaf");
}
public static <T extends Comparable> T min(T[] arr) {
if (arr == null || arr.length == 0) {
return null;
}
T min = arr[0];
for (int i = 0; i < arr.length; i++) {
if (min.compareTo(arr[i]) > 0) {
min = arr[i];
}
}
return min;
}
限定T是Comparable或Comparable的子类。
虚拟机没有泛型类型对象,所有对象都是普通类。
public static void main(String[] args) {
// 限定String类型
Pair<String> pair = new Pair<String>("2134","sfsdf");
String first = pair.getFirst();
// pair2没有指定类型,first1只能知道是Object
Pair pair2 = pair;
Object first1 = pair2.getFirst();
// 编译报错
String first2 = pair2.getFirst();
}
public class Apple<T extends Number> {
T size;
public Apple(T size) {
this.size = size;
}
public T getSize() {
return size;
}
public void setSize(T size) {
this.size = size;
}
}
public static void main(String[] args) {
Apple<Integer> apple = new Apple<>(6);
// 这里返回Integer对象
Integer size = apple.getSize();
// apple2丢失尖括号的类型信息,apple2只能知道Number类型
Apple apple2 = apple;
Number size1 = apple2.getSize();
// 编译报错
Integer size2 = apple2.getSize();
}
public static void main(String[] args) {
ArrayList<String> arrayString = new ArrayList<String>();
ArrayList<Integer> arrayInteger = new ArrayList<Integer>();
System.out.println(arrayString.getClass() == arrayInteger.getClass());
}
运行结果为true。getClass()总是返回原始类型。
类型通配符: ?,代表任意类型。
extends T>, 意思是需要一个T类型或者T类型的子类。 适用于消费集合元素为主的场景。
public class Animal {
}
Cat继承Animal 。
public class Cat extends Animal {
}
public static void handle(List<? extends Animal> list) {
for (Animal animal : list) {
System.out.println(animal);
}
// 编译报错,不能添加元素
list.add(new Animal());
list.add(new Cat());
}
super T>,意思是需要一个T类型或者T类型的父类。适用于生产元素为主的场景。
public static void handle2(List<? super Cat> list) {
// 只能是Object
for (Object cat : list) {
System.out.println(cat);
}
// 编译报错
for (Cat cat : list) {
System.out.println(cat);
}
list.add(new Cat());
}
public static void main(String[] args) {
// 1.继承关系:Object > Animal > Cat > WhiteCat
List<Animal> animals = new ArrayList<>();
List<Cat> cats = new ArrayList<>();
List<WhiteCat> whiteCats = new ArrayList<>();
animals.add(new Animal());
cats.add(new Cat());
whiteCats.add(new WhiteCat());
// 2.测试赋值操作
// 下一行报错,只能赋值给Cat或Cat之类
List<? extends Cat> extendsCatFromAnimal = animals;
List<? super Cat> superCatFromAnimal = animals;
List<? extends Cat> extendsCatFromCat = cats;
List<? super Cat> superCatFromCat = cats;
List<? extends Cat> extendsCatFromWhiteCat = whiteCats;
// 报错,只能赋值给Cat或Cat的父类
List<? super Cat> superCatFromWhiteCat = whiteCats;
// 3.测试add方法
// 均报错,无法add
extendsCatFromCat.add(new Animal());
extendsCatFromCat.add(new Cat());
extendsCatFromCat.add(new WhiteCat());
// 下一行报错,只能添加Cat或Cat的子类
superCatFromCat.add(new Animal());
superCatFromCat.add(new Cat());
superCatFromCat.add(new WhiteCat());
// 4.测试get方法
// 所有super操作都能够返回元素,不过泛型丢失,只能是Object类型
Object object = superCatFromAnimal.get(0);
Object object2 = superCatFromCat.get(0);
Object object3 = superCatFromWhiteCat.get(0);
// 均可以返回
Cat cat = extendsCatFromAnimal.get(0);
Cat cat1 = extendsCatFromCat.get(0);
// 报错,虽然WhiteCat继承Cat,但类型擦除之后是不知道的
WhiteCat cat2 = extendsCatFromWhiteCat.get(0);
}
Type接口有四个子接口GenericArrayType,ParameterizedType,TypeVariable,WildcardType和一个实现类Class。
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ANNOTATION_TYPE, CONSTRUCTOR, FIELD,
METHOD, PACKAGE, PARAMETER, TYPE, TYPE_PARAMETER, TYPE_USE})
public @interface Custom {
}
public class MyTypeTest<K, V extends @Custom Number & Serializable> {
private Number number;
public K k;
public V v;
public List<K> list = new ArrayList<>();
public Map<String, K> map = new HashMap<>();
public K[] tArray;
public List<K>[] ltArray;
public MyTypeTest testClass;
public MyTypeTest<K, Integer> testClass2;
public Map<? super String, ? extends Number> mapWithWildcard;
/**
* 泛型构造函数
*
*/
public <X extends Number> MyTypeTest(X x, K k) {
this.k = k;
number = x;
}
/**
* 泛型方法
*/
public <Y extends K> void method(Y y) {
k = y;
}
}
/**
* 这是各种类型变量的通用接口,类型变量是在反射方法需要时首次创建
*/
interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
//返回此类型参数的上界列表,如果没有上界则放回Object. 例如 V extends @Custom Number & Serializable 这个类型参数,
// 有两个上界,Number 和 Serializable
Type[] getBounds();
//类型参数声明时的载体,例如 `class TypeTest` ,那么V 的载体就是MyTypeTest
D getGenericDeclaration();
// 类型变量的名称
String getName();
//Java 1.8加入 AnnotatedType: 如果这个这个泛型参数类型的上界用注解标记了,我们可以通过它拿到相应的注解
AnnotatedType[] getAnnotatedBounds();
}
public static void main(String[] args) throws Exception {
// 获取成员变量属性v
Field field = MyTypeTest.class.getField("v");
// 获取属性的类型变量
TypeVariable typeVariable = (TypeVariable) field.getGenericType();
System.out.println("类型变量的名称:" + typeVariable);
System.out.println("类型变量的上界:" + Arrays.asList(typeVariable.getBounds()));
System.out.println("类型变量的载体:" + typeVariable.getGenericDeclaration());
System.out.println("类型变量的名称:" + typeVariable.getName());
// 如果泛型参数的上界有注解标记,可以通过这个拿到注解
AnnotatedType[] annotatedBounds = typeVariable.getAnnotatedBounds();
System.out.println("泛型参数的上界注解1:" + Arrays.asList(annotatedBounds));
System.out.println("泛型参数的上界注解2:" + Arrays.asList(annotatedBounds[0].getAnnotations()));
}
执行结果。
类型变量的名称:V
类型变量的上界:[class java.lang.Number, interface java.io.Serializable]
类型变量的载体:class com.freedom.algorithm.generic.MyTypeTest
类型变量的名称:V
泛型参数的上界注解1:[@com.freedom.algorithm.generic.Custom() java.lang.Number, java.io.Serializable]
泛型参数的上界注解2:[@com.freedom.algorithm.generic.Custom()]
/**
* ParameterizedType是指参数化类型,比如: Collection.
/
interface ParameterizedType extends Type {
// 获取参数类型<>里面的那些值,例如Map 那么就得到 [K,V]的一个数组
Type[] getActualTypeArguments();
// 获取参数类型<>前面的值,例如Map 那么就得到 Map
Type getRawType();
// 获取其父类的类型,例如Map 有一个内部类Entry, 那么在Map.Entry 上调用这个方法就可以获得 Map
Type getOwnerType();
}
public static void main(String[] args) throws Exception {
Field listField = MyTypeTest.class.getField("list");
Type genericType1 = listField.getGenericType();
System.out.println("参数化类型1:" + genericType1.getTypeName()); //参数类型1:java.util.List
Field mapField = MyTypeTest.class.getField("map");
Type genericType2 = mapField.getGenericType();
System.out.println("参数类型2:" + genericType2.getTypeName());//参数类型2:java.util.Map
if (genericType2 instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) genericType2;
Type[] types = pType.getActualTypeArguments();
System.out.println("参数类型列表:" + Arrays.asList(types));//参数类型列表:[class java.lang.String, T]
System.out.println("参数原始类型:" + pType.getRawType());//参数原始类型:interface java.util.Map
System.out.println("参数父类类型:" + pType.getOwnerType());//参数父类类型:null,因为Map没有外部类,所以为null
}
}
执行结果:
参数化类型1:java.util.List<K>
参数类型2:java.util.Map<java.lang.String, K>
参数类型列表:[class java.lang.String, K]
参数原始类型:interface java.util.Map
参数父类类型:null
/**
* 泛型数组类型,其基本类型是参数化类型或者类型变量,比如List ,K[]。
* GenericArrayType represents an array type whose component type is either a parameterized type or a type variable.
/
public interface GenericArrayType extends Type {
// 获取泛型类型数组的声明类型,即获取数组方括号 [] 前面的部分
Type getGenericComponentType();
}
public static void main(String[] args) throws Exception {
Field tArrayField = MyTypeTest.class.getField("tArray");
GenericArrayType genericType = (GenericArrayType) tArrayField.getGenericType();
System.out.println("数组参数类型1:" + genericType);
TypeVariable typeVariable = (TypeVariable) genericType.getGenericComponentType();
System.out.println("typeVariable:" + typeVariable);
Field ltArrayField = MyTypeTest.class.getField("ltArray");
GenericArrayType genericType2 = (GenericArrayType) ltArrayField.getGenericType();
System.out.println("数组参数类型2:" + genericType2);
ParameterizedType parameterizedType = (ParameterizedType) genericType2.getGenericComponentType();
System.out.println("parameterizedType:" + parameterizedType);//数组参数类型3:T
}
执行结果
数组参数类型1:K[]
typeVariable:K
数组参数类型2:java.util.List<K>[]
parameterizedType:java.util.List<K>
// WildcardType represents a wildcard type expression, such as ?, ? extends Number, or ? super Integer.
// 通配符类型,即带有?的泛型参数, 例如 List>中的?,List extends Number>里的? extends Number 和List super Integer>的? super Integer 。
public interface WildcardType extends Type {
// 获取上界
Type[] getUpperBounds();
// 获取下界
Type[] getLowerBounds();
}
public static void main(String[] args) throws Exception {
Field mapWithWildcard = MyTypeTest.class.getField("mapWithWildcard");
//先获取属性的泛型类型 Map super String, ? extends Number>
Type wild = mapWithWildcard.getGenericType();
if (wild instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) wild;
//获取<>里面的参数变量 ? super String, ? extends Number
Type[] actualTypes = pType.getActualTypeArguments();
System.out.println("全部类型:" + Arrays.asList(actualTypes));
//? super java.lang.String
WildcardType first = (WildcardType) actualTypes[0];
//? extends java.lang.Number
WildcardType second = (WildcardType) actualTypes[1];
//WildcardType2: lower:[class java.lang.String] upper:[class java.lang.Object]
System.out.println("super 类型的: lower:" + Arrays.asList(first.getLowerBounds()) +
" upper:" + Arrays.asList(first.getUpperBounds()));
//WildcardType3: lower:[] upper:[class java.lang.Number]
System.out.println("extends 类型的: lower:" + Arrays.asList(second.getLowerBounds()) +
" upper:" + Arrays.asList(second.getUpperBounds()));
}
}
执行结果
全部类型:[? super java.lang.String, ? extends java.lang.Number]
super 类型的: lower:[class java.lang.String] upper:[class java.lang.Object]
extends 类型的: lower:[] upper:[class java.lang.Number]
参考文章:秒懂Java类型(Type)系统 https://blog.csdn.net/ShuSheng0007/article/details/89520530