“Type接口:Java中的类型”的版本间差异

来自Wikioe
跳到导航 跳到搜索
(创建页面,内容为“category:Java == 关于 == '''Type''' 是 Java 编程语言中'''所有类型的公共高级接口''',也就是 Java 中所有类型的“父类”(也是 Class 类的父类)。 Type 体系中的类型包括: # <span style="color: blue">'''原始类型'''(Class)</span>:不仅仅包含我们平常所指的'''类''',还包括'''枚举、数组、注解'''等。 # <span style="color: blue">'''参数化类型'''(ParameterizedType)</span>…”)
 
(Eijux移动页面Type:Java中的类型Type接口:Java中的类型,不留重定向)
(没有差异)

2022年12月27日 (二) 23:03的版本


关于

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 接口

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

位于:“java.lang.reflect”包

Type:

package java.lang.reflect;

public interface Type {
    default String getTypeName() {
        return toString();
    }
}
  • 与其相关的子接口和子接口实现类:
    1. ParameterizedType:【子接口】参数化类型
      • 实现类:ParameterizedTypeImpl
    2. GenericArrayType:【子接口】泛型数组类型
      • 实现类:GenericArrayTypeImpl
    3. TypeVariable:【子接口】类型变量
      • 实现类:TypeVariableImpl
    4. WildcardType:【子接口】泛型表达式(通配符表达式)
      • 实现类:WildcardTypeImpl
    5. Class:【实现类】原始类型
    • 子接口和实现类,位于:“java.lang.reflect
    • 子接口的实现类,位于:“sun.reflect.generics.reflectiveObjects

【子接口】ParameterizedType

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

GenericArrayType接口:

package java.lang.reflect;

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

【子接口】TypeVariable

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

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(子接口、实现类)示例

示例: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,须在类上进行声明。

参考