Java 类型系统

Type

TypeJava中所有类型的父接口。

其子类和子接口如下:

  1. Class<T>
  2. TypeVariable<D>
  3. ParameterizedType
  4. GenericArrayType
  5. WildcardType

Type 只有一个默认方法:

// 返回描述类型的字符串
default String getTypeName() {
        return toString();
}

Class<T>

Class<T> 封装了一个具体类的属性操作和反射操作,T是具体类;

Class<T> 实现了以下四个接口:

  • Serializable
  • GenericDeclaration
  • Type
  • AnnotatedElement

Serializable

并无接口方法,作为序列化标记;

GenericDeclaration

GenericDeclaration 是所有声明了类型变量的类的公用接口;

只有一个接口方法:

// 用于获取类型变量的数组
public TypeVariable<?>[] getTypeParameters();

用法如下:

val clazz = Map::class.java
val list = clazz.typeParameters
list.forEach {
    println("${it.name} ${it.bounds.map { bound-> bound.typeName }}")
}

运行结果:

K [java.lang.Object]
V [java.lang.Object]

Map类的声明如下:

public interface Map<K, out V> {
	......
}

Type

Class<T> 实现了Type 唯一的接口方法,具体实现如下:

public String getTypeName() {
        if (isArray()) {
            try {
                Class<?> cl = this;
                int dimensions = 0;
                while (cl.isArray()) {
                    dimensions++;
                    cl = cl.getComponentType();
                }
                StringBuilder sb = new StringBuilder();
                sb.append(cl.getName());
                for (int i = 0; i < dimensions; i++) {
                    sb.append("[]");
                }
                return sb.toString();
            } catch (Throwable e) { /*FALLTHRU*/ }
        }
        return getName();
}

对数组类型和非数组类型分别处理,具体细节按下不表;

用法如下:

val clazz = Map::class.java
println(clazz.typeName)

val array = Array<IntArray>(3){
    it -> intArrayOf(0)
}
println(array.javaClass.typeName)

结果如下:

java.util.Map
int[][]

AnnotatedElement

定义了一系列获取注解的接口方法,所有可以被注解标记的元素都应该实现这个接口;

在讲解接口方法之前需要了解各种注解的分类:

directly present

直接出现在元素上的注解;

indirectly present

@Repeatable标记的注解,然后该注解出现在元素上;

@Target(ElementType.TYPE)  
@Retention(RetentionPolicy.RUNTIME)
public @interface Persons {
	Person[] value();
}

@Repeatable(Persons.class)
public @interface Person{
	String role() default "";
}

@Person(role="CEO")
@Person(role="husband")
@Person(role="father")
@Person(role="son")
public class Man {
	String name= "";
}

Person注解相对于Man就是indirectly present的,Persons相对于Mandirectly presentPersonPersons的参数;

present

分为两种情况:

  1. directly present
  2. @Inherited标记的注解 A,然后注解A出现在B的父类C上,则A相对与Bpresent的;

associated

分为三种情况:

  1. directly present
  2. indirectly present
  3. 第三种情况有四个小条件,注解为A,元素为E
    • 注解A没有直接或者间接出现在元素E
    • 元素E 是一个类
    • 注解A@Inherited 标记
    • 注解A 和元素E的父类的关系为associated

isAnnotationPresent()

方法声明:

default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)

指定注解是否为present状态;

getAnnotation()

方法声明:

<T extends Annotation> T getAnnotation(Class<T> annotationClass)

如果给定的注解处于present状态,则返回注解,否则返回null

getAnnotations()

方法声明:

Annotation[] getAnnotations();

获取所有处于present状态的注解,若无符合条件的数组,则返回大小为0的数组;

getAnnotationsByType()

方法声明:

default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)

获取所有处于associated状态的注解;

getDeclaredAnnotation()

方法声明:

default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass)

如果给定的注解处于directly present状态,则返回注解,反则返回null

getDeclaredAnnotationsByType()

方法声明:

default <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass)

如果给定的注解处于directly present或者indirectly present状态,返回注解数组;

getDeclaredAnnotations()

方法声明:

Annotation[] getDeclaredAnnotations()

获取所有处于directly present状态的注解;

具体方法讲解

toString()

public String toString() {
    return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
            + getName();
}

描述当前Class文件,文件类型和文件的全限定名;

toGenericString()

描述当前Class文件,包括修饰符和类型变量;

forName()

静态方法,根据全限定名获取Class;

newInstance()

调用无参的构造函数,返回实例;

isInstance()

instanceof 关键字作用相同;

isAssignableFrom()

如果给定的参数为当前Class的父类或者父接口,则返回true,否则返回false;

isInterface()

当前Class是否为接口;

isArray()

当前Class是否为数组;

isPrimitive()

当前Class是否为基础数据类型;

包括:Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE;

isAnnotation()

当前Class是否为注解;

isSynthetic()

当前Class是否为合成类;

合成类指的是在编译时引入的类,例如匿名类;

getName()

获取当前Class的名称;

分为三种情况:

  • Class是引用类型,则返回其全限定名;
  • Class是基本数据类型,则返回相应的关键字;
  • Class 是数组类型,规则如下

getClassLoader()

获取当前Class的类加载器;

getTypeParameters()

详见 GenericDeclaration

getSuperclass()

获取其父类的Class

getGenericSuperclass()

获取其直接父类的Type

getPackage()

获取当前Classpackage

getInterfaces()

获取当前Class所有实现的接口Class数组;

getGenericInterfaces()

获取当前Class所有直接实现的接口Type数组;

getComponentType()

如果当前Class是数组,则返回数组元素类型Class

如果当前Class不是数组,则返回null

getModifiers()

获取当前Class的修饰符;

getEnclosingMethod()

如果当前Class是一个函数中的匿名类,则返回该函数,否则返回null

getEnclosingConstructor()

如果当前Class是一个构造函数中的匿名类,则返回构造函数,否则返回null

getDeclaringClass()

如果当前Class是另一个Class B的成员变量,则返回Class B,否则返回null

getEnclosingClass()

返回声明当前Class的外部类;

getSimpleName()

对于普通类和基本类型返回其类名;

对于匿名类返回空串;

对于数组返回"${类名}[]";

getTypeName()

详见 Type

getCanonicalName()

返回其全限定名;

isAnonymousClass()

是否为匿名类;

isLocalClass()

是否为local class

local class指的是声明在函数体内部的类;

isMemberClass()

当前Class是否为内部类;

getClasses()

获取定义在当前类内部的public类或者接口,包括来自父类的内部类和接口;

getFields()

获取当前类的所有公开字段,包括来自父类的字段;

getMethods()

获取当前类的所有公开方法,包括来自父类和父接口的公开方法;

getConstructors()

获取当前类的所有公开构造方法;

getField()

根据给定的字符串返回当前类的公开字段;

getMethod()

根据方法签名,获得当前的类的指定公开方法;

getConstructor()

根据给定参数,获取当前类的公开构造方法;

getDeclaredClasses()

获取定义在当前类内部的类或者接口,包括来自父类和父接口的任何修饰符的类;

getDeclaredFields()

获取当前类的所有字段,不包括继承自其他类的的字段;

getDeclaredMethods()

获取当前类的所有方法,不包括继承自其他类的方法;

getDeclaredConstructors()

获取当前类的所有构造方法;

getDeclaredField()

根据给定的字段名,获取字段,包括私有字段;

getDeclaredMethod()

根据方法签名,获取指定方法,包括私有方法;

getDeclaredConstructor()

根据给定参数,获取指定构造方法;

getResourceAsStream()

根据参数返回InputStream,具体实现在类加载器中;

getResource()

根据参数返回URL,具体实现在类加载器中;

getProtectionDomain()

返回ProtectionDomain,这个类封装类一些权限安全相关的代码;

isEnum()

判断是否类枚举类;

cast()

进行类型转换;

asSubclass()

如果当前类是给定类的子类,则进行类型转换;否则抛出异常;

getAnnotatedSuperclass()

获取父类的注解类型;

Class clazz = java.util.HashMap.class;        
System.out.println(
clazz.getAnnotatedSuperclass().getType().getTypeName());

结果如下:

java.util.AbstractMap<K, V>

getAnnotatedInterfaces()

获取当前类的所有父类和父接口的注解类型;

Class clazz = java.util.HashMap.class;
AnnotatedType[] typeList = clazz.getAnnotatedInterfaces();
for (AnnotatedType type : typeList) {
    System.out.println(type.getType().getTypeName());
}

结果如下:

java.util.Map<K, V>
java.lang.Cloneable
java.io.Serializable

TypeVariable

public static class GenericBean<K> {
        // 类型变量
        K key;
        // 参数化类型
        List<K> kList;
    }

public static void main(String[] args) {

    try {
            GenericBean bean = new GenericBean<String>();
            Field fk;
            fk = GenericBean.class.getDeclaredField("key");
            Type eyType =  fk.getGenericType();

            if (eyType instanceof ParameterizedType) {
                System.out.println("ParameterizedType: true");
            }

            if (eyType instanceof TypeVariable) {
                System.out.println("TypeVariable: true");
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
}

执行结果:

TypeVariable: true

getBounds()

获取该泛型的上下界;

public static class GenericBean<K> {
        // 类型变量
        K key;
        // 参数化类型
        List<K> kList;
    }

    public static void main(String[] args) {

        try {
            GenericBean bean = new GenericBean<String>();
            Field fk;
            fk = GenericBean.class.getDeclaredField("key");
            Type eyType =  fk.getGenericType();

            if (eyType instanceof TypeVariable) {
                System.out.println("TypeVariable: true");
                TypeVariable variable = (TypeVariable) eyType;
                Type[] bounds = variable.getBounds();
                for (Type bound : bounds) {
                    System.out.println(bound.getTypeName());
                }
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

执行结果:

TypeVariable: true
java.lang.Object

getGenericDeclaration()

获取当前类的泛型声明;

    public static class GenericBean<K, V> {
        // 类型变量
        K key;
        // 参数化类型
        List<K> kList;
    }

    public static void main(String[] args) {

        try {
            GenericBean bean = new GenericBean<String, String>();
            Field fk;
            fk = GenericBean.class.getDeclaredField("key");
            Type eyType =  fk.getGenericType();

            if (eyType instanceof TypeVariable) {
                System.out.println("TypeVariable: true");
                TypeVariable variable = (TypeVariable) eyType;
                GenericDeclaration declaration = variable.getGenericDeclaration();
                TypeVariable<?>[] parameters = declaration.getTypeParameters();
                for (TypeVariable parameter : parameters) {
                    System.out.println(parameter.getName());
                }
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
}

执行结果:

TypeVariable: true
K
V

可以根据泛型声明获取当前所有的泛型;

getName()

返回泛型名称;

public static class GenericBean<K, V> {
        // 类型变量
        K key;
        // 参数化类型
        List<K> kList;
    }

    public static void main(String[] args) {

        try {
            GenericBean bean = new GenericBean<String, String>();
            Field fk;
            fk = GenericBean.class.getDeclaredField("key");
            Type eyType =  fk.getGenericType();

            if (eyType instanceof TypeVariable) {
                System.out.println("TypeVariable: true");
                TypeVariable variable = (TypeVariable) eyType;
                System.out.println(variable.getName());
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

执行结果:

TypeVariable: true
K

getAnnotatedBounds()

获取上下界的注解类型;

public static class GenericBean<K, V> {
        // 类型变量
        K key;
        // 参数化类型
        List<K> kList;
    }

    public static void main(String[] args) {

        try {
            GenericBean bean = new GenericBean<String, String>();
            Field fk;
            fk = GenericBean.class.getDeclaredField("key");
            Type eyType =  fk.getGenericType();

            if (eyType instanceof TypeVariable) {
                System.out.println("TypeVariable: true");
                TypeVariable variable = (TypeVariable) eyType;
                AnnotatedType[] list = variable.getAnnotatedBounds();
                for (AnnotatedType type : list) {
                    System.out.println(type.getType().getTypeName());
                }
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

执行结果:

TypeVariable: true
java.lang.Object

ParameterizedType

public static class GenericBean<K, V> {
        // 类型变量
        K key;
        // 参数化类型
        List<V> kList;
    }

    public static void main(String[] args) {

        try {
            GenericBean bean = new GenericBean<String, String>();
            Field fk;
            fk = GenericBean.class.getDeclaredField("kList");
            Type eyType =  fk.getGenericType();

            if (eyType instanceof ParameterizedType) {
                System.out.println("ParameterizedType: true");
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

执行结果:

ParameterizedType: true

getActualTypeArguments()

获取该字段生命的所有泛型数组;

public static class GenericBean<K, V> {
        // 类型变量
        K key;
        // 参数化类型
        Map<K,V> kMap;
    }

    public static void main(String[] args) {

        try {
            GenericBean bean = new GenericBean<String, String>();
            Field fk;
            fk = GenericBean.class.getDeclaredField("kMap");
            Type eyType =  fk.getGenericType();

            if (eyType instanceof ParameterizedType) {
                System.out.println("ParameterizedType: true");
                ParameterizedType variable = (ParameterizedType) eyType;
                Type[] list = variable.getActualTypeArguments();

                for (Type type : list) {
                    System.out.println(type.getTypeName());
                }

            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

执行结果:

ParameterizedType: true
K
V

getRawType()

获取参数化类型字段的原生类型;

public static class GenericBean<K, V> {
        // 类型变量
        K key;
        // 参数化类型
        Map<K,V> kMap;
    }

    public static void main(String[] args) {

        try {
            GenericBean bean = new GenericBean<String, String>();
            Field fk;
            fk = GenericBean.class.getDeclaredField("kMap");
            Type eyType =  fk.getGenericType();

            if (eyType instanceof ParameterizedType) {
                System.out.println("ParameterizedType: true");
                ParameterizedType variable = (ParameterizedType) eyType;
                Type type = variable.getRawType();

                System.out.println(type.getTypeName());
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

执行结果:

ParameterizedType: true
java.util.Map

getOwnerType()

解释比较复杂,请看代码:

public class Test {

    public static class GenericBean<K, V> {
        // 类型变量
        K key;
        // 参数化类型
        Map<K,V> kMap;

        MemberBean<K> bean;
    }

    public static class MemberBean<K> {

    }

    public static void main(String[] args) {

        try {
            GenericBean bean = new GenericBean<String, String>();
            Field fk;
            fk = GenericBean.class.getDeclaredField("bean");
            Type eyType =  fk.getGenericType();

            if (eyType instanceof ParameterizedType) {
                System.out.println("ParameterizedType: true");
                ParameterizedType variable = (ParameterizedType) eyType;
                Type type = variable.getOwnerType();

                if (type == null) {
                    System.out.println("type is null");
                } else {
                    System.out.println(type.getTypeName());
                }
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

执行结果:

ParameterizedType: true
Test

GenericArrayType

泛型数组;

getGenericComponentType()

获取泛型名称;

public static class GenericBean<K extends InputStream, V> {
        // 类型变量
        K key;
        // 参数化类型
        Map<K, V> kMap;

        K[] kArray;
    }

    public static void main(String[] args) {

        try {
            GenericBean bean = new GenericBean<FileInputStream, String>();
            Field fk;
            fk = GenericBean.class.getDeclaredField("kArray");
            Type eyType = fk.getGenericType();

            if (eyType instanceof GenericArrayType) {
                System.out.println("GenericArrayType: true");
                GenericArrayType variable = (GenericArrayType) eyType;
                Type type = variable.getGenericComponentType();
                
                System.out.println(type.getTypeName());
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

执行结果:

GenericArrayType: true
K

WildcardType

通配符泛型;

public static class GenericBean {
        List<? extends String> kList;
    }

    public static void main(String[] args) {

        try {
            Field fk = GenericBean.class.getDeclaredField("kList");
            Type eyType = fk.getGenericType();

            if (eyType instanceof ParameterizedType) {
                System.out.println("ParameterizedType: true");
                ParameterizedType parameterizedType = (ParameterizedType) eyType;
                WildcardType variable = (WildcardType) parameterizedType.getActualTypeArguments()[0];

                Type[] upperBounds = variable.getUpperBounds();
                Type[] lowerBounds = variable.getLowerBounds();

                if (upperBounds.length == 0) {
                    System.out.println("upperBounds is empty");
                } else {
                    for (Type type : upperBounds) {
                        System.out.println(type.getTypeName());
                    }
                }

                System.out.println();

                if (lowerBounds.length == 0) {
                    System.out.println("lowerBounds is empty");
                } else {
                    for (Type type : lowerBounds) {
                        System.out.println(type.getTypeName());
                    }
                }
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

执行结果:

ParameterizedType: true
java.lang.String

lowerBounds is empty
posted @ 2021-05-23 22:11  ijkzen  阅读(125)  评论(0编辑  收藏  举报