Java Type类型详解

Java Type类型详解,第1张

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、List带有类型参数的类型,也可以是自定义的,再调用getRawType()与getActualTypeArguments()两个方法,就可以得到声明此参数化类型的类(java.lang.Comparable)和实际的类型参数数组([? super T]),而这个? super T又是一个WildcardType类型。

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/906352.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-15
下一篇 2022-05-15

发表评论

登录后才能评论

评论列表(0条)