Type是Java 编程语言中所有类型的公共高级接口(官方解释),也就是Java中所有类型的“爹”;其中,“所有类型”的描述尤为值得关注。它并不是我们平常工作中经常使用的 int、String、List、Map等数据类型,而是从Java语言角度来说,对基本类型、引用类型向上的抽象;
Type体系中类型的包括:原始类型(Class)、参数化类型(ParameterizedType)、数组类型(GenericArrayType)、类型变量(TypeVariable)、基本类型(Class);
原始类型,不仅仅包含我们平常所指的类,还包括枚举、数组、注解等;
参数化类型,就是我们平常所用到的泛型List、Map;
数组类型,并不是我们工作中所使用的数组String[] 、byte[],而是带有泛型的数组,即T[] ;
基本类型,也就是我们所说的java的基本类型,即int,float,double等
Type的直接子接口
- ParameterizedType: 表示一种参数化的类型,比如Collection,即普通的泛型。
ParameterizedType 是参数化类型,即泛型,类似List、Map
public interface ParameterizedType extends Type {
// 获取泛型的类型,比如 Map 获取的是 Integer和String
Type[] getActualTypeArguments();
// 获取<> 前面的类型,比如 Map 获取的是Map
Type getRawType();
// For example, if this type is {@code O.I}, return a representation of {@code O}.
Type getOwnerType();
}
示例
public class Test {
public static void main(String[] args) {
Field[] declaredFields = Person.class.getDeclaredFields();
for(Field f:declaredFields){
if(f.getGenericType() instanceof ParameterizedType){
ParameterizedType genericType = (ParameterizedType) f.getGenericType();
System.out.println(String.format("%s 属性的原生类型为%s,参数类型有",f.getName(),genericType.getRawType()));
for(Type type : genericType.getActualTypeArguments()){
System.out.println(type);
}
System.out.println("================");
}
}
}
}
class Person {
List<Integer> integerList;
Map<String,Integer> belongs;
}
// 输出
属性 integerList 的原生类型为interface java.util.List,参数类型有
class java.lang.Integer
================
属性 belongs 的原生类型为interface java.util.Map,参数类型有
class java.lang.String
class java.lang.Integer
================
- TypeVariable:是各种类型变量的公共父接口,就是泛型里面的类似T、E。 ** 在这需要强调的是,TypeVariable代表着泛型中的变量,而ParameterizedType则代表整个泛型; **
认识TypeVariable之前,我们先来看另一个接口 GenericDecalaration
public interface GenericDeclaration extends AnnotatedElement {
/**
* 返回的泛型变量数组代表了泛型声明的内容,TypeVariable类型就是定义泛型变量的。
*/
public TypeVariable<?>[] getTypeParameters();
}
GenericDeclaration 有三个直接子类 Class,Construtor,Method,也就是说只能在这几种对象上进行范型变量的声明(定义)。GenericDeclaration的接口方法getTypeParameters用来逐个获取该GenericDeclaration的范型变量声明。
//1.在类(Class)上声明(定义)类型变量
class A<T>{
T a;
}//之后这里可用任意类型替换T,例如
A<String> as = new A<String>();
//是否看着有点像集合?不错,集合就是泛型的一个典型运用
//2.在方法上声明(定义,方法上,类型变量声明(定义)不是在参数里边,而且必须在返回值之前,static等修饰后
public <E> void test(E e){}
//3.声明(定义)在构造器上
public <K> A(K k){}
【注意】类型变量声明(定义)的时候不能有下限(既不能有super),否则编译报错。为什么?T extends classA表示泛型有上限classA,当然可以,因为这样,每一个传进来的类型必定是classA(具有classA的一切属性和方法),但若是T super classA,传进来的类型不一定具有classA的属性和方法,当然就不适用于泛型
[extends 和 super的区别]
关键字说明
? 通配符类型
<? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类
<? super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object
看了这个我是不太明白,换成白话是这个意思:
List<? extends T> 是说 这个list放的是T或者T的子类型的对象,但是不能确定具体是什么类型,所以可以get(),不能add()(可以add null值)
List<? super T> 是说这个list放的是至少是T类型的对象,所以我可以add T或者T的子类型,但是get得到的类型不确定,所以不能获取
public class TestSuperExtends {
public static void main(String[] args) {
// 造数
List<Apple> apples = new ArrayList<>();
apples.add(new Apple());
apples.add(new Apple());
apples.add(new Apple());
ArrayList<Food> foods = new ArrayList<>();
ArrayList<RedApple> redApples = new ArrayList<>();
// 任何Food的子类的列表都能赋值成功,也可以取值,但是不能添加除null以外的元素
List<? extends Food> foodList = apples;
// foodList.add(new Apple()); // error
// foodList.add(new Food()); // error
foodList.add(null);
test(foods);
// 因为super表示下届,所以foods和apples都可以赋值成功,但是Apple的子类不行。
List<? super Apple> list1 = foods;
List<? super Apple> list = apples;
// List super Apple> list2 = redApples; // error
// 可以添加Apple及其子类,但是不是添加任何Apple的父类
// list.add(new Food()); // error
list.add(new Apple());
list.add(new RedApple());
Object object = list.get(0);
}
public static <T extends Food> void test(List<T> foods){
for(T f:foods){
f.eat();
}
}
}
我们知道Object类有一个方法, getClass(), 它返回当前实例的运行时类, 而Class是 GenericDeclaration 的子类,所以 Java所有的类都能通过调用 getTypeParameters() 方法获取到类型变量.
TypeVariable是类型变量,如参数化类型中的E、K等类型变量,表示泛指任何类,如果加上extends/super限定,则就会有相应的上限、下限。
public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
/**
* 获得该类型变量的上限(上边界),若无显式定义(extends),默认为Object,类型变量的上限可能不止一个,因为可以用&符号限定多个(这其中有且只能有一个为类或抽象类,且必须放在extends后的第一个,即若有多个上边界,则第一个&后必为接口)
* 比如 xxxClass,则返回 List和Serialize
*/
Type[] getBounds();
/**
* 获取的是在哪个类上进行的泛型声明,在如上的例子中,返回的是xxxClass
* @since 1.5
*/
D getGenericDeclaration();
/**
* 同样是上面的例子,返回 K, 也就是泛型类型声明时写的名字
*/
String getName();
/**
*
* @since 1.8
*/
AnnotatedType[] getAnnotatedBounds();
}
public class Test<K extends List & Serializable, V> {
public static void main(String[] args) {
TypeVariable[] v = new Test().getClass().getTypeParameters();
for(TypeVariable t:v){
System.out.println(Arrays.stream(t.getBounds()).map(Type::getTypeName).collect(Collectors.toList()));
System.out.println(t.getName());
System.out.println(t.getGenericDeclaration());
System.out.println("-----------------");
}
}
}
打印输出如下
[java.util.List, java.io.Serializable]
K
class com.lion.converter.test.Test
-----------------
[java.lang.Object]
V
class com.lion.converter.test.Test
- GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型,比如List<>[],T[]这种。
public interface GenericArrayType extends Type {
/**
* 获取泛型数组中元素的类型,要注意的是:
无论从左向右有几个[]并列,这个方法仅仅脱去最右边的[]之后剩下的内容就作为这个方法的返回值。
*/
Type getGenericComponentType();
}
- WildcardType:代表一种通配符类型表达式,类似? super T这样的通配符表达式。
WildcardType是通配符表达式,或泛型表达式,它虽然是Type的一个子接口,但并不是Java类型中的一种,表示的仅仅是类似 ? extends T、? super K这样的通配符表达式。
public interface WildcardType extends Type {
/**
* 获取泛型表达式上界
*/
Type[] getUpperBounds();
/**
* 获取泛型表达式下界
*/
Type[] getLowerBounds();
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)