杰瑞科技汇

Java的type与class究竟有何本质区别?

  • Type (类型) 就像“交通工具”这个概念,它是一个抽象的、广泛的分类。
  • Class (类) 就像“汽车”、“自行车”、“飞机”这些具体的交通工具,它们都是“交通工具”这个概念的具体实例。

下面我们来详细拆解这两个概念的关系和区别。

Java的type与class究竟有何本质区别?-图1
(图片来源网络,侵删)

java.lang.reflect.Type (接口)

Type 是 Java 反射 API 中的一个顶层接口,位于 java.lang.reflect 包下,它是一个标记接口,本身不包含任何方法,它的作用是作为所有 Java 类型的“根”或“通用表示”。

Type 的主要“子类”或实现包括:

  1. Class: 这是最常见、最核心的类型表示。
  2. ParameterizedType (参数化类型): 表示带有类型参数的类型,List<String>Map<String, Integer>
  3. TypeVariable (类型变量): 表示泛型类型变量,例如类定义中的 T (如 class Box<T>)。
  4. WildcardType (通配符类型): 表示通配符类型,, ? extends Number, ? super Integer
  5. GenericArrayType (泛型数组类型): 表示元素类型是泛型参数的数组,T[]List<String>[]

Type 的特点:

  • 广义性: 它涵盖了 Java 中所有的类型,包括原始类型、参数化类型、类型变量、通配符等。
  • 概念性: 它是一个类型系统中的抽象概念,是反射 API 用来统一描述各种类型的工具。
  • 接口: 它是一个接口,不是具体的类。

java.lang.Class (类)

Class 类是 Java 反射机制的基石。每一个类在 JVM 中加载后,都会有一个对应的 Class 对象。 这个 Class 对象包含了该类的完整信息,如字段、方法、构造器、父类、接口等。

Java的type与class究竟有何本质区别?-图2
(图片来源网络,侵删)

Class 对象的特点:

  • 具体性: 它代表了一个具体的、已定义的类或接口String.class 代表 String 这个类,List.class 代表 List 这个接口。
  • 运行时信息: Class 对象在 JVM 加载类时被创建,并存在于整个程序运行期间,它是获取类信息的唯一途径。
  • Type 的实现: Class 实现了 Type 接口,这意味着 Class 对象本身就是一个 Type,你可以将任何 Class 实例直接用作 Type

核心区别与关系

特性 Type (接口) Class (类)
本质 一个概念性的接口,是所有 Java 类型的顶层抽象 一个具体的类,代表 JVM 中已加载的类或接口
范围 更广,包括 ClassParameterizedTypeTypeVariable 等。 较窄,只代表具体的类和接口。List<String> 的类型是 ParameterizedType,而不是 Class
实例化 你不能直接实例化 Type 接口,它的实例是 ClassParameterizedType 等具体类的对象。 每个类在 JVM 中有且仅有一个 Class 对象,可以通过 ClassName.classobject.getClass() 获取。
关系 Class 实现了 Type 接口。ClassType 的一种。 Class Type 的一个具体子集。

代码示例

让我们通过代码来直观地感受它们的区别和联系。

示例 1: Class 作为 Type

这是最常见的情况,当你获取一个类的类型时,你得到的就是它的 Class 对象,而这个对象也同时是一个 Type

import java.lang.reflect.Type;
public class ClassAsTypeExample {
    public static void main(String[] args) {
        // 获取 String 类的 Class 对象
        Class<String> stringClass = String.class;
        // Class 实现了 Type 接口,所以可以安全地赋值给 Type 变量
        Type stringType = stringClass;
        System.out.println("Class 对象: " + stringClass);
        System.out.println("Type 对象: " + stringType);
        System.out.println("它们是同一个对象吗? " + (stringClass == stringType)); // true
        // 在泛型方法中使用
        printType(stringType); // 传入 Type
        printType(stringClass); // 传入 Class,因为 Class 是 Type 的子类型
    }
    public static void printType(Type type) {
        System.out.println("传入的 Type 类型是: " + type.getTypeName());
    }
}

输出:

Class 对象: class java.lang.String
Type 对象: class java.lang.String
它们是同一个对象吗? true
传入的 Type 类型是: java.lang.String
传入的 Type 类型是: java.lang.String

示例 2: Type 的其他实现(非 Class 类型)

当你处理泛型时,你会遇到不是 ClassType

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
public class OtherTypesExample {
    public static void main(String[] args) {
        // 1. ParameterizedType (参数化类型)
        // List<String> 的类型不是 Class,而是 ParameterizedType
        Type listType = new Object() {}.getClass().getGenericSuperclass(); // 一种获取 ParameterizedType 的技巧
        // 更简单直接的例子:
        Type mapType = Map.class.getGenericSuperclass(); // 这通常返回 Object 的 Type,我们换一个方式
        // 假设我们有一个类来持有这个类型
        class MyListHolder {
            List<String> myList;
        }
        Type fieldType = MyListHolder.class.getDeclaredField("myList").getGenericType();
        if (fieldType instanceof ParameterizedType) {
            ParameterizedType pType = (ParameterizedType) fieldType;
            System.out.println("ParameterizedType: " + pType);
            System.out.println("原始类型: " + pType.getRawType()); // 得到 List.class
            System.out.println("类型参数: " + pType.getActualTypeArguments()[0]); // 得到 String.class
        }
        // 2. TypeVariable (类型变量)
        class Box<T> {
            T content;
        }
        Type tFieldType = Box.class.getDeclaredField("content").getGenericType();
        if (tFieldType instanceof java.lang.reflect.TypeVariable) {
            java.lang.reflect.TypeVariable<?> tType = (java.lang.reflect.TypeVariable<?>) tFieldType;
            System.out.println("\nTypeVariable: " + tType.getName()); // 输出 T
        }
    }
}

输出:

ParameterizedType: java.util.List<java.lang.String>
原始类型: interface java.util.List
类型参数: class java.lang.String
TypeVariable: T

从上面的例子可以看出,List<String> 的“类型”是一个 ParameterizedType 对象,它内部包含了原始类型 List.class 和类型参数 String.class,这说明 Type 的范畴远比 Class 要大。


Type Class
一句话概括 Java 类型系统的顶层接口,是所有类型的抽象。 JVM 中已加载类的具体表示,是 Type 最常见的实现。
关系 Class is a Type Class implements Type
使用场景 当你需要处理泛型时,必须使用 Type,因为它能表示 List<T> 这样的复杂类型,反射 API 中很多方法的参数和返回值都是 Type 当你处理具体的、已知的类或接口时使用,String.classobject.getClass(),这是最常用的反射操作。

记住这个核心:Type 是一个广义的概念,而 Class 是这个概念中最具体、最常用的一种。 在日常开发中,你大部分时间都在和 Class 打交道,但在处理高级泛型时,Type 及其子类(如 ParameterizedType)就变得至关重要了。

分享:
扫描分享到社交APP
上一篇
下一篇