Type接口:Java中的类型

来自Wikioe
跳到导航 跳到搜索


关于

Type 是 Java 编程语言中所有类型的公共高级接口,也就是 Java 中所有类型的“父类”(也是 Class 类的父类)。

Type 体系中的类型包括:

  1. 原始类型(Class):不仅仅包含我们平常所指的,还包括枚举、数组、注解等。
  2. 参数化类型(ParameterizedType):即,平常所用到的泛型 List<>、Map<>。
  3. 数组类型(GenericArrayType):特指,带有泛型、参数化类型的数组(如,T[]) 。
    • 注意,并非常用的类型数组(如,String[] 、byte[]);
  4. 基本类型(Class),即,Java 的基本类型(byte、short、int、long、float、double、char)。

Type 接口[1]

Type 是个空接口,没有定义任何方法,通过多态提高了程序的扩展性。

位于:“java.lang.reflect”包

Type接口:

package java.lang.reflect;

public interface Type {
    default String getTypeName() {
        return toString();
    }
}

Type 相关的子接口和子接口实现类:

  1. ParameterizedType[2]:参数化类型。
    • 如:“List<T>”、“Map<String, Integer>”
    • 实现类:ParameterizedTypeImpl
  2. GenericArrayType[2]:“参数化类型”/“类型变量”的数组类型。
    • 如:“T[]”、“List<String>[]”
    • 实现类:GenericArrayTypeImpl
  3. TypeVariable[2]:类型变量。 ——【泛型声明时所用的变量,即为“类型变量”】
    • 如:“T”、“List<T>”中的“T” ——【TypeVariable 只表示“类型变量”本身,区别于“参数化类型”】
    • 实现类:TypeVariableImpl
  4. WildcardType[2]:泛型表达式(通配符表达式)。
    • 如:“List<? extends Number>”、“List<? super String>”
    • 实现类:WildcardTypeImpl
  5. Class:原始类型。
    • 以上几种 Type 以外(即,普通的对象)就是一个 Class 类型,是 Type 中的一种。
子接口和实现类,位于:“java.lang.reflect”
子接口的实现类,位于:“sun.reflect.generics.reflectiveObjects

【子接口】ParameterizedType

package java.lang.reflect;

/**
 * ParameterizedType 表示一个“参数化的类型”,如“Collection<String>”
 *
 * 1、参数化类型是在反射方法首次需要时创建的,如此包中指定。
 * 2、创建参数化类型 p 时,解析 p 实例化的泛型类型声明,并递归创建 p 的所有“类型参数”(TypeVariable)。
 * 3、重复创建参数化类型无效。
 *
 * 实现此接口的类的实例必须实现 equals() 方法:
 *     该方法将“共享相同泛型类型声明,并具有相等类型参数”的任意两个实例等效。
 *
 * @since 1.5
 */
public interface ParameterizedType extends Type {
    /**
     * 返回【表示“此类型的实际类型参数”的{@code Type}对象数组】
	 * ————【即,获取“<>”中的实际类型】
     *
	 *
     * 注意,在某些情况下,返回的数组为空。
	 *     如果此类型表示嵌套在参数化类型中的非参数化类型,则可能发生这种情况。
     */
    Type[] getActualTypeArguments();

    /**
     * 返回【表示“声明此类型的类或接口”的{@code Type}对象】
	 * ————【即,获取“<>”前的实际类型】
     */
    Type getRawType();

    /**
     * 返回【表示“此类型所属类型”的{@code Type}对象】
	 * ————【即,获取该类型(为内部类)的外部类的类型】
	 *
     * 注意,如果此类型是顶级类型,则返回{@code null}。
     */
    Type getOwnerType();
}

【子接口】GenericArrayType

package java.lang.reflect;

/**
 * GenericArrayType 表示其组件类型为“参数化类型”(ParameterizedType)或“类型变量”(TypeVariable)的数组类型。
 *
 * @since 1.5
 */
public interface GenericArrayType extends Type {
    /**
     * 返回【表示“此数组的组件类型”的{@code Type}对象】
	 * ————【即,获取数组元素的实际类型】
     */
    Type getGenericComponentType();
}

【子接口】TypeVariable

package java.lang.reflect;

/**
 * TypeVariable 是各种“类型变量”的通用超级接口。
 * 
 * 1、类型变量是在反射方法第一次需要时创建的,如此包中所指定的。
 * 2、如果类型变量 t 被类型(即类、接口或注释类型)T 引用,
 *    并且 T 由 T 的第 n 个封闭类声明,
 *    则创建 t 需要解析 T 的第 i 个封闭类,其中 i=0 到 n(含)。
 * 3、创建类型变量不能导致创建其边界。
 * 4、重复创建类型变量无效。
 *
 * @since 1.5
 */
public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
    /**
     * 返回【表示“此‘类型变量’上限”的{@code Type}对象数组】
	 * ————【即,获取该“类型变量”的上限】
	 * 
	 * 注意,如果没有显式声明上限,则上限为{@code Object}。
     */
    Type[] getBounds();

    /**
     * 返回【表示“此‘类型变量’声明的泛型声明”的{@code GenericDeclaration}对象】
	 * ————【即,获取声明该“类型变量”的实体(类、方法、构造器)】
     */
    D getGenericDeclaration();

    /**
     * 返回【源代码中出现的此‘类型变量’的名称】
     */
    String getName();

    /**
     * 返回一个 AnnotatedType 对象的数组,用于表示此 TypeVariable 表示的类型参数的上限。
	 * 数组中对象的顺序与类型参数声明中边界的顺序相对应。
     *
     * 注意,如果类型参数声明无边界,则返回长度为 0 的数组。
     */
     AnnotatedType[] getAnnotatedBounds();
}

【子接口】WildcardType

package java.lang.reflect;

/**
 * WildcardType 表示通配符类型表达式。
 * 例如{@code ?}、{@code ? extends Number}或{@ccode ? super Integer}。
 *
 * @since 1.5
 */
public interface WildcardType extends Type {
    /**
     * 返回【表示此类型变量上限的{@code Type}对象数组】
	 * ————【即,获取通配符“extends”的类型】
     */
    Type[] getUpperBounds();

    /**
     * 返回【表示此类型变量下限的{@code Type}对象数组】
	 * ————【即,获取通配符“super”的类型】
     */
    Type[] getLowerBounds();
}

【实现类】Class

在 Java 中,每个“.class”文件在程序运行期间,都对应着一个 Class 对象,这个对象保存有这个类的全部信息。

因此,Class 对象也称之为【Java 反射的基础】;

Type(子接口、实现类)示例[3]

示例:ParameterizedType

package com.eijux.springdemo1;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

public class ParameterizedTypeDemo<T> {
    private List<T> list = null;
    private Map<String, Integer> map = null;
    private Map.Entry<String, Integer> mapEntry;

    public static void testParameterizedType() throws NoSuchFieldException {
        /** fieldList 变量:
         * 类型:Field
         * 值:"com.eijux.springdemo1.ParameterizedTypeDemo.list"
         */
        Field fieldList = ParameterizedTypeDemo.class.getDeclaredField("list");
        /**
         *  Field.getGenericType(): 获取【表示“Field 的类型”的 Type】
         *  返回一个 {@code Type} 对象,该对象表示此 {@code Field} 对象所表示的字段的声明类型。
         *
         * typeList 变量:
         *  类型:Type
         *      实际类型:ParameterizedTypeImpl(ParameterizedType 的实现类)
         *      使用时可能需要强制类型转换
         *  值:"java.util.List<T>"
         */
        Type typeList = fieldList.getGenericType();

        /**
         * Object.getClass(): 返回此 {@code Object} 的【运行时类型(实际类型)】。
         * 返回的 {@code Class} 对象是由所表示类的 {@code 静态同步} 方法锁定的对象。
         *
         * Type.getTypeName(): 返回描述此类型的字符串,包括有关任何类型参数的信息。
         */
        System.out.println(typeList.getClass().getName());  // sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
        System.out.println(typeList.getTypeName().toString());  // java.util.List<T>
    }

    public static void testGetActualTypeArguments() throws NoSuchFieldException {
        Field fieldMap = ParameterizedTypeDemo.class.getDeclaredField("map");
        // 强制类型转换:Type -> ParameterizedType(实际使用其实现类 ParameterizedTypeImpl)
        ParameterizedType parameterizedTypeMap = (ParameterizedType) fieldMap.getGenericType();

        /**
         * ParameterizedType.getActualTypeArguments(): 获取【表示“泛型的实际类型”的 Type】
         * 可能会存在多个泛型,例如 Map<K,V>,会返回 Type[];
         */
        Type[] types = parameterizedTypeMap.getActualTypeArguments();

        System.out.println(types[0]);   // class java.lang.String
        System.out.println(types[1]);   // class java.lang.Integer
    }

    public static void testGetRawType() throws NoSuchFieldException {
        Field fieldMap = ParameterizedTypeDemo.class.getDeclaredField("map");
        // 强制类型转换:Type -> ParameterizedType(实际使用其实现类 ParameterizedTypeImpl)
        ParameterizedType parameterizedTypeMap = (ParameterizedType) fieldMap.getGenericType();

        /**
         * ParameterizedType.getRawType(): 获取【表示“声明泛型的类或者接口”的 Type】
         * 即,泛型声明的“<>”前面的那个值,例如 Map<K,V> 将返回“表示 Map 的 Type”
         */
        Type type = parameterizedTypeMap.getRawType();

        System.out.println(type);   // interface java.util.Map
    }

    public static void testGetOwnerType() throws NoSuchFieldException {
        Field fieldMapEntry = ParameterizedTypeDemo.class.getDeclaredField("mapEntry");
        // 强制类型转换:Type -> ParameterizedType(实际使用其实现类 ParameterizedTypeImpl)
        ParameterizedType parameterizedTypeMapEntry = (ParameterizedType) fieldMapEntry.getGenericType();

        /**
         * ParameterizedType.getOwnerType(): 获取【表示“泛型的拥有者”的 Type】
         * 即,若该泛型为某类的内部类,则可以获取该泛型的父类的 Type
         * 例如,Map.Entry<String, Integer> 将返回“表示 Map 的 Type”
         */
        Type type = parameterizedTypeMapEntry.getOwnerType();

        System.out.println(type);   // interface java.util.Map
    }

    public static void main(String[] agrs) throws NoSuchFieldException {
        testParameterizedType();
        testGetActualTypeArguments();
        testGetRawType();
        testGetOwnerType();
    }
}

示例:GenericArrayType

package com.eijux.springdemo1;

import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Type;
import java.util.List;

public class GenericArrayTypeDemo<T> {
    private T[] t;
    private List<String>[] listArray;

    public static void testGenericArrayType() throws NoSuchFieldException {
        /** fieldT 变量:
         * 类型:Field
         * 值:"com.eijux.springdemo1.GenericArrayTypeDemo.t"
         */
        Field fieldT = GenericArrayTypeDemo.class.getDeclaredField("t");
        /**
         *  Field.getGenericType(): 获取【表示“Field 的类型”的 Type】
         *  返回一个 {@code Type} 对象,该对象表示此 {@code Field} 对象所表示的字段的声明类型。
         *
         * typeList 变量:
         *  类型:Type
         *      实际类型:GenericArrayTypeImpl(GenericArrayType 的实现类)
         *      使用时可能需要强制类型转换
         *  值:"T[]"
         */
        Type typeList = fieldT.getGenericType();
        /**
         * Object.getClass(): 返回此 {@code Object} 的【运行时类型(实际类型)】。
         * 返回的 {@code Class} 对象是由所表示类的 {@code 静态同步} 方法锁定的对象。
         *
         * Type.getTypeName(): 返回描述此类型的字符串,包括有关任何类型参数的信息。
         */
        System.out.println(typeList.getClass().getName());  // sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
        System.out.println(typeList.getTypeName().toString());  // T[]
    }

    public static void testGetGenericComponentType() throws NoSuchFieldException {
        Field fieldListArray = GenericArrayTypeDemo.class.getDeclaredField("listArray");
        // 强制类型转换:Type -> GenericArrayType(实际使用其实现类 GenericArrayTypeImpl)
        GenericArrayType genericArrayType = (GenericArrayType) fieldListArray.getGenericType();

        /**
         * GenericArrayType.getGenericComponentType(): 获取【表示“泛型数组的元素”的 Type】
         * 无论是几维数组,getGenericComponentType()方法都只会脱去最右边的[]
         */
        Type type = genericArrayType.getGenericComponentType();

        System.out.println(type);   // java.util.List<java.lang.String>
    }

    public static void main(String[] args) throws NoSuchFieldException {
        testGenericArrayType();
        testGetGenericComponentType();
    }
}

示例:TypeVariable

package com.eijux.springdemo1;

import java.io.Serializable;
import java.lang.reflect.*;
import java.util.List;

public class TypeVariableDemo<T extends Number & Serializable & Comparable> {
    private T t;
    private List<T> list;

    public static void testTypeVariable() throws NoSuchFieldException {
        /** fieldList 变量:
         * 类型:Field
         * 值:"com.eijux.springdemo1.TypeVariableDemo.list"
         */
        Field fieldList = TypeVariableDemo.class.getDeclaredField("list");
        /**
         *  Field.getGenericType(): 获取【表示“Field 的类型”的 Type】
         *  返回一个 {@code Type} 对象,该对象表示此 {@code Field} 对象所表示的字段的声明类型。
         *
         * typeList 变量:
         *  类型:Type
         *      实际类型:ParameterizedTypeImpl(ParameterizedType 的实现类)
         *      使用时可能需要强制类型转换
         *  值:"java.util.List<T>"
         */
        Type typeList = fieldList.getGenericType();
        /**
         * ParameterizedType.getActualTypeArguments(): 获取【表示“泛型的实际类型”的 Type】
         * 可能会存在多个泛型,例如 Map<K,V>,会返回 Type[];
         */
        Type[] type = ((ParameterizedType) typeList).getActualTypeArguments();

        System.out.println(type[0].getClass()); // class sun.reflect.generics.reflectiveObjects.TypeVariableImpl
    }

    public static void testGetBounds() throws NoSuchFieldException {
        Field fieldT = TypeVariableDemo.class.getDeclaredField("t");
        // 强制类型转换:Type -> TypeVariable(实际使用其实现类 TypeVariableImpl)
        TypeVariable typeVariable = (TypeVariable) fieldT.getGenericType();

        /**
         * TypeVariable.getBounds(): 获取【表示“泛型的类型变量的上限”的 Type】
         * 该变量可能会 extend 多个类型,所以返回值为 Type[] 数组;
         * 如果未显式声明上限,则上限为 {@code Object}。
         */
        Type[] types = typeVariable.getBounds();

        for(Type type : types){
            System.out.println(type);
            // class java.lang.Number
            // interface java.io.Serializable
            // interface java.lang.Comparable
        }
    }

    public static void testGetGenericDeclaration() throws NoSuchFieldException {
        Field fieldT = TypeVariableDemo.class.getDeclaredField("t");
        // 强制类型转换:Type -> TypeVariable(实际使用其实现类 TypeVariableImpl)
        TypeVariable typeVariable = (TypeVariable) fieldT.getGenericType();

        /**
         * TypeVariable.getGenericDeclaration(): 获取【“声明该类型变量的实体(GenericDeclaration)”】
         * 即,“类型变量的声明位置”
         */
        GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();

        System.out.println(genericDeclaration);   // class com.eijux.springdemo1.TypeVariableDemo
    }

    public static void testGetName() throws NoSuchFieldException {
        Field fieldT = TypeVariableDemo.class.getDeclaredField("t");
        // 强制类型转换:Type -> TypeVariable(实际使用其实现类 TypeVariableImpl)
        TypeVariable typeVariable = (TypeVariable) fieldT.getGenericType();

        /**
         * TypeVariable.getGenericDeclaration(): 获取【“类型变量在源码中定义的名称”】
         * 即,“类型变量的声明位置”
         */
        String name = typeVariable.getName();

        System.out.println(name);   // T
    }

    public static void main(String[] agrs) throws NoSuchFieldException {
        testTypeVariable();
        testGetBounds();
        testGetGenericDeclaration();
        testGetName();
    }
}

示例:WildcardType

package com.eijux.springdemo1;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.List;

public class WildcardTypeDemo {
    private List<? extends Number> listNum;
    private List<? super String> listStr;

    public static void testWildcardTypeDemo() throws NoSuchFieldException {
        Field fieldListNum = WildcardTypeDemo.class.getDeclaredField("listNum");
        // 强制类型转换:Type -> ParameterizedType(实际使用其实现类 ParameterizedTypeImpl)
        ParameterizedType typeListNum = (ParameterizedType) fieldListNum.getGenericType();
        // 获取:表示“泛型的实际类型”的 Type
        Type[] typesListNum = typeListNum.getActualTypeArguments();
        System.out.println(typesListNum[0].getClass()); //class sun.reflect.generics.reflectiveObjects.WildcardTypeImpl
    }

    public static void testGetUpperBounds() throws NoSuchFieldException {
        Field fieldListNum = WildcardTypeDemo.class.getDeclaredField("listNum");
        // 强制类型转换:Type -> ParameterizedType(实际使用其实现类 ParameterizedTypeImpl)
        ParameterizedType typeListNum = (ParameterizedType) fieldListNum.getGenericType();
        // 获取:表示“泛型的实际类型“的 Type
        Type[] typesListNum = typeListNum.getActualTypeArguments();

        /**
         * WildcardType.getUpperBounds(): 获取【表示“泛型通配符的类型上限”的 Type】
         * 通配符可能会 extend 多个类型,所以返回值为 Type[] 数组;
         */
        Type[] types = ((WildcardType) typesListNum[0]).getUpperBounds();
        for (Type type : types) {
            System.out.println(type);
            // class java.lang.Number
        }
    }

    public static void testGetLowerBounds() throws NoSuchFieldException {
        Field fieldListStr = WildcardTypeDemo.class.getDeclaredField("listStr");
        // 强制类型转换:Type -> ParameterizedType(实际使用其实现类 ParameterizedTypeImpl)
        ParameterizedType typeListStr = (ParameterizedType) fieldListStr.getGenericType();
        /**
         * ParameterizedType.getActualTypeArguments(): 获取【表示“泛型的实际类型”的 Type】
         * 可能会存在多个泛型,例如 Map<K,V>,会返回 Type[];
         */
        Type[] typesListStr = typeListStr.getActualTypeArguments();

        /**
         * WildcardType.getUpperBounds(): 获取【表示“泛型通配符的类型上限”的 Type】
         * 通配符可能会 super 多个类型,所以返回值为 Type[] 数组;
         */
        Type[] types = ((WildcardType) typesListStr[0]).getUpperBounds();
        for (Type type : types) {
            System.out.println(type);
            // class java.lang.Object
        }
    }

    public static void main(String[] args) throws NoSuchFieldException {
        testWildcardTypeDemo();
        testGetUpperBounds();
        testGetLowerBounds();
    }
}

示例:Class

package com.eijux.springdemo1;

import java.lang.reflect.Field;
import java.lang.reflect.Type;

public class ClassDemo {
    private ClassDemo classDemo;

    public static void testClassDemo() throws NoSuchFieldException {
        /** fieldList 变量:
         * 类型:Field
         * 值:"com.eijux.springdemo1.ClassDemo.classDemo"
         */
        Field field = ClassDemo.class.getDeclaredField("classDemo");
        /**
         *  Field.getGenericType(): 获取【表示“Field 的类型”的 Type】
         *  返回一个 {@code Type} 对象,该对象表示此 {@code Field} 对象所表示的字段的声明类型。
         *
         * typeList 变量:
         *  类型:Type
         *      实际类型:Class(Type 的子类)
         *  值:"class com.eijux.springdemo1.ClassDemo"
         */
        Type type = field.getGenericType();

        System.out.println(type);   // class com.eijux.springdemo1.ClassDemo
    }

    public static void main(String[] args) throws NoSuchFieldException {
        testClassDemo();
    }
}

相关:GenericDeclaration

GenericDeclaration声明“类型变量”的所有实体的公共接口。

    ——即,该接口定义了哪些地方可以定义“类型变量”(泛型)

GenericDeclaration接口:

package java.lang.reflect;

/**
 * 声明类型变量的所有实体的公共接口。
 *
 * @since 1.5
 */
public interface GenericDeclaration extends AnnotatedElement {
    /**
     * 按声明顺序返回{@code TypeVariable}对象数组,
	 * 这些对象表示由此{@code GenericDeclaration}对象表示的泛型声明声明的类型变量。
	 * 
	 * 注意,如果基础泛型声明未声明类型变量,则返回长度为0的数组。
     */
    public TypeVariable<?>[] getTypeParameters();
}

“GenericDeclaration实现类”与“类型变量的声明位置”

GenericDeclaration 有三个实现类,表示可以声明“类型变量(泛型)”的位置:

  1. Class:表示“在‘类’上声明泛型”。
    示例:
    /** 
     * 在【类】上声明“类型变量”
     */
    public class GenericDeclarationTest<T> {
    	...
    }
    
  2. Constructor:表示“在‘构造方法’上声明泛型”。
    • 继承于:抽象类“Executable”;
    示例:
    public class GenericDeclarationTest {
    	/** 
    	 * 在【构造方法】上声明“类型变量”
    	 */
    	public <T> GenericDeclarationTest (T t) {
    		...
    	}
    	
    	...
    }
    
  3. Method:表示“在‘方法’上声明泛型”。
    • 继承于:抽象类“Executable”;
    示例:
    public class GenericDeclarationTest {
    	...
    	
    	/** 
    	 * 在【方法】上声明“类型变量”
    	 */
    	public <T> void test(T t) {
    		...
    	}
    }
    


特别注意:属性上只能使用,而不能定义“类型变量”

示例:

public class GenericDeclarationTest {
	private T;
	private List<T> list;
	
	...
}
如上,属性中使用的 T,须在类上进行声明。

参考

  1. 参考:“java.lang.reflect”包相关源码
  2. 2.0 2.1 2.2 2.3 ParameterizedType、GenericArrayType、TypeVariable、WildcardType 的区别与关联:
    1. GenericArrayType 表示 ParameterizedType / TypeVariable 类型的数组。
      • “元素类型”通过 GenericArrayType.getGenericComponentType() 获取;
      • “元素类型”:
        可以为 ParameterizedType 类型(如“List<T>[]”的元素),
        也可以为 TypeVariable 类型(如“T[]”的元素);
    2. ParameterizedType 表示“参数化类型”整体。
      • “类型参数”通过 ParameterizedType.getActualTypeArguments() 获取;
      • “类型参数”:
        可以为 TypeVariable 类型(如“List<T>”的类型参数),
        也可以是 Class 类型(如“List<String>”的类型参数);
    3. TypeVariable 仅表示“类型变量”。
    4. WildcardType 仅表示“泛型表达式”。
    以如下代码为例:
    public class TypeDemo<T> {
    	private T[] t;
    	
    	private List<T> list_1;
    	private List<String> list_2;
    	
    	private List<T>[] listArray_1;
    	private List<String>[] listArray_2;
    	
    	private List<? super String> listStr;
    	
    	...
    }
    
    1. t:
      类型:ParameterizedType
      类型参数:“T”,其类型:TypeVariable
    2. list_1:
      类型:ParameterizedType
      类型参数:“T”,其类型:TypeVariable
    3. list_2:
      类型:ParameterizedType
      类型参数:“String”,其类型:Class
    4. listArray_1:
      类型:GenericArrayType
      元素:“List<T>”,其类型:ParameterizedType
      元素的类型参数:“T”,其类型:TypeVariable
    5. listArray_2:
      类型:GenericArrayType
      元素:“List<String>”,其类型:ParameterizedType
      元素的类型参数:“String”,其类型:Class
    6. listStr:
      类型:ParameterizedType
      通配符表达式:“? super String”,其类型:WildcardType
  3. 参考:Java中的Type