Java Type总结

Type

转载自:java知识总结之Type - 简书 (jianshu.com) 并进行了简单修改

Type是Java 编程语言中所有类型的公共高级接口(官方解释),也就是Java中所有类型的“爹”,它并不是我们平常工作中经常使用的 int、String、List、Map等数据类型,而是从Java语言角度来说,对基本类型、引用类型向上的抽象;

Type体系中类型的包括:

  • 原始类型(Type):不仅仅包含我们平常所指的类,还包括枚举、数组、注解等
  • 参数化类型(ParameterizedType):就是我们平常所用到的泛型List、Map<K,V>,Set,Class<?>
  • 数组类型(GenericArrayType):并不是我们工作中所使用的数组String[] 、byte[],而是带有泛型的数组,即T[]
  • 类型变量(TypeVariable):比如 T a
  • 基本类型(Class):原始类型,每个类(貌似接口也有)都会有个Class对象

Type及相关类所在包位置:java.lang.reflect

Type类几乎在各种框架中都能看到,尤其是涉及代理,反射的业务。理解好Type类也会对今后框架封装,源码解读有很大好处。

Type与子类,子接口的关系

image-20220619220222920

Type

public interface Type {
    /**
     * Returns a string describing this type, including information
     * about any type parameters.
     *
     * @implSpec The default implementation calls {@code toString}.
     *
     * @return a string describing this type
     * @since 1.8
     */
    default String getTypeName() {
        return toString();
    }
}

从java1.8开始,type默认有个getTypeName()方法

ParameterizedType

参数化类型,即带参数的类型,也可以说带<>的类型。例如List<String>, User<T> 等。

public interface ParameterizedType extends Type {
    // 获取<>中实际的类型参数,以Type数组形式返回
    Type[] getActualTypeArguments();
    // 获取<>前面的类型
    Type getRawType();
    // 如果这个类型是某个类型所属,则获取这个所有者的类型,否则返回null,比如Map.Entry<Sting,String>,会返回Map
    Type getOwnerType();
}

TypeVariable

类型变量,即泛型中的变量;例如:T、K、V等变量,可以表示任何类;在这需要强调的是,TypeVariable代表着泛型中的变量,而ParameterizedType则代表整个泛型;

public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
    // 获取泛型的上限,无显示定义(extends),默认为Object
    Type[] getBounds();
    // 获取声明改类型变量实体(即获取类,方法或构造器名)
    D getGenericDeclaration();
    // 获取名称,即K、V、E之类名称
    String getName();
    // 
     AnnotatedType[] getAnnotatedBounds();
}

GenericArrayType

泛型数组类型,用来作为数组的泛型声明类型,用来描述ParameterizedType、TypeVariable类型的数组;例如List<T>[] ltArrayT[] tArray两个数组,其中List<T>[], 和T[]就是GenericArrayType类型。

public interface GenericArrayType extends Type {
    // 获得这个数组元素类型,比如T[]  则获得T的type
    Type getGenericComponentType();
}

GenericArrayType 接口只有一个方法getGenericComponentType(),其可以用来获取数组方括号 [] 前面的部分,例如T[],在其上调用getGenericComponentType 就可以获得T. 值得注意的是多维数组得到的是最后一个[] 前面的部分,例如T[][], 得到的是T[].

Class

与上三种不同,Class是Type的一个实现类,属于原始类型,是Java反射的基础,对java类的的抽象。在程序运行期间,每一个类都对应一个Class对象,这个对象包含了类的修饰符、方法、属性、构造等信息,所以我们可以对这个Class对象进行相应的操作,这就是Java的反射。

WildcardType

泛型表达式(或者通配符表达式),即即带有?的泛型参数,如List<?>中的List<? extends Number>里的? extends NumberList<? super Integer>? super Integer;WildcardType虽然是Type的子接口,但却不是Java类型中的一种:

public interface WildcardType extends Type {
    // 获取泛型表达式上界(上限extends)
    Type[] getUpperBounds();
    // 获取泛型表达式下界(下限super)
    Type[] getLowerBounds();
}

示例代码

package jdk.type;

import org.junit.Test;

import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;

/**
 * @author liuyang
 * 创建时间: 2022-06-19 20:09
 */
public class TypeTest {

    public static void main(String[] args) throws Exception {
        String[] strings = new String[]{"1", "2"};
        Class<? extends String[]> clazz = strings.getClass();
        if (clazz.isArray()) {
            Class<?> componentType = clazz.getComponentType();
            System.out.println(componentType);
        }
    }

    @Test
    public void testParameterizedType() throws Exception {
        parseType(ParameterizedTypeTest.class);

        System.out.println();
        parseType(GenericArrayTypeTest.class);

        System.out.println();
        parseType(TypeVariableTest.class);

        System.out.println();
        parseType(WildcardTypeTest.class);
    }

    private static String getTypes(Type[] types) {
        StringJoiner joiner = new StringJoiner(";");
        for (Type type : types) {
            joiner.add(appendType(type));
        }
        return joiner.toString();
    }

    private static String appendType(Type type) {
        StringJoiner joiner = new StringJoiner(";");
        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            for (int i = 0; i < actualTypeArguments.length; i++) {
                Type actualTypeArgument = actualTypeArguments[i];
                String msg = String.format("ActualTypeArgument[%s]=%s", i, actualTypeArgument);
                if (actualTypeArgument instanceof WildcardType) {
                    WildcardType wildcardType = (WildcardType) actualTypeArgument;
                    msg += " wildcardType LowerBounds=" + getTypes(wildcardType.getLowerBounds()) + ";UpperBounds=" + getTypes(wildcardType.getUpperBounds());
                }
                joiner.add(msg);
            }
        } else {
            return type.getTypeName();
        }
        return joiner.toString();
    }

    public void parseType(Class<?> clazz) throws Exception {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            String name = field.getName();
            Type genericType = field.getGenericType();
            String typeName = genericType.getTypeName();
            if (genericType instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) genericType;
                Type rawType = parameterizedType.getRawType();
                Type ownerType = parameterizedType.getOwnerType();
                String argMsg = appendType(parameterizedType);
                String msg = String.format("%s的typeName=%s,rawType=%s,ownerType=%s,arguments=%s", name, typeName, rawType, ownerType, argMsg);
                System.out.println(msg);
            } else if (genericType instanceof GenericArrayType) {
                GenericArrayType genericArrayType = (GenericArrayType) genericType;
                Type genericComponentType = genericArrayType.getGenericComponentType();
                String genericName = genericComponentType.getClass().getName();
                String msg = String.format("%s的typeName=%s,genericComponentType=%s,genericName=%s", name, typeName, genericComponentType, genericName);
                System.out.println(msg);
            } else if (genericType instanceof TypeVariable) {
                TypeVariable typeVariable = (TypeVariable) genericType;
                Type[] bounds = typeVariable.getBounds();
                StringJoiner joiner = new StringJoiner(";");
                for (int i = 0; i < bounds.length; i++) {
                    joiner.add("type bounds[" + i + "] Type name: " + bounds[i].getTypeName());
                }
                GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
                String msg = String.format("%s的typeName=%s,bounds=%s,GenericDeclaration=%s", name, typeName, joiner, genericDeclaration);
                System.out.println(msg);
            }
        }
    }

    public static class WildcardTypeTest {
        List<? extends String> a;
    }

    public static class TypeVariableTest<T> {
        T a;
        List<String> b;
    }

    public static class GenericArrayTypeTest<T> {
        private T[] t;
        private List<String>[] lists;
    }

    public static class ParameterizedTypeTest<T> {
        private List<T> list = null;
        private Set<T> set = null;
        private Map<String, T> map = null;
        private Map.Entry<String, Integer> map2;
    }
}
list的typeName=java.util.List<T>,rawType=interface java.util.List,ownerType=null,arguments=ActualTypeArgument[0]=T
set的typeName=java.util.Set<T>,rawType=interface java.util.Set,ownerType=null,arguments=ActualTypeArgument[0]=T
map的typeName=java.util.Map<java.lang.String, T>,rawType=interface java.util.Map,ownerType=null,arguments=ActualTypeArgument[0]=class java.lang.String;ActualTypeArgument[1]=T
map2的typeName=java.util.Map$Entry<java.lang.String, java.lang.Integer>,rawType=interface java.util.Map$Entry,ownerType=interface java.util.Map,arguments=ActualTypeArgument[0]=class java.lang.String;ActualTypeArgument[1]=class java.lang.Integer

t的typeName=T[],genericComponentType=T,genericName=sun.reflect.generics.reflectiveObjects.TypeVariableImpl
lists的typeName=java.util.List<java.lang.String>[],genericComponentType=java.util.List<java.lang.String>,genericName=sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl

a的typeName=T,bounds=type bounds[0] Type name: java.lang.Object,GenericDeclaration=class jdk.type.TypeTest$TypeVariableTest
b的typeName=java.util.List<java.lang.String>,rawType=interface java.util.List,ownerType=null,arguments=ActualTypeArgument[0]=class java.lang.String

a的typeName=java.util.List<? extends java.lang.String>,rawType=interface java.util.List,ownerType=null,arguments=ActualTypeArgument[0]=? extends java.lang.String wildcardType LowerBounds=;UpperBounds=java.lang.String
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值