### 1、为什么需要类型分析？

在开发框架时，经常需要在运行时获取泛型的真实类型信息。例如：

- JSON 反序列化时，需要知道 `List` 字段的元素是 `String` 还是 `UserModel`
- ORM 框架映射查询结果时，需要知道 `Map` 的 Key 和 Value 分别是什么类型
- 依赖注入容器在解析泛型依赖时，需要获取完整的泛型参数信息

Java 的泛型在编译后会被擦除，运行时只能看到原始类型。TypeEggg 通过解析匿名子类的父类签名，在运行时还原泛型信息。

---

TypeEggg 是 EggG 的两大核心能力之一，它对 `java.lang.reflect.Type` 进行了统一包装，提供类型判断和泛型信息访问能力。

### 2、TypeEggg 概述

TypeEggg 提供以下能力：

1. **类型识别** — 判断是普通 Class、参数化类型、还是类型变量
2. **泛型参数提取** — 获取 `Map<K, V>` 中 `K → String`、`V → UserModel` 等对应关系
3. **原始类型获取** — 返回擦除后的 `Class` 对象（默认 `Object.class`）
4. **JDK 类型判断** — 区分业务自定义类型和 JDK 内置类型

### 3、基本用法

#### 获取 TypeEggg

```java
Eggg eggg = new Eggg();

// 方式一：通过匿名子类保留泛型信息
TypeEggg typeEggg = eggg.getTypeEggg(new HashMap<String, Integer>() {}.getClass());

// 方式二：通过已有的 Type 对象
TypeEggg typeEggg = eggg.getTypeEggg(myType);
```

> **原理**：Java 的泛型在编译后会被擦除。但创建匿名子类 `new HashMap<String, Integer>() {}`（注意末尾的 `{}`）时，编译器会在其父类签名中保留泛型参数信息，TypeEggg 可以从中解析出完整的泛型类型。

#### 类型判断

TypeEggg 提供一组 `isXxx()` 方法用于快速判断类型：

```java
TypeEggg t = eggg.getTypeEggg(new ArrayList<String>() {}.getClass());

t.isCollection();         // true
t.isList();               // true
t.isSet();                // false
t.isMap();                // false
t.isArray();              // false
t.isEnum();               // false
t.isPrimitive();          // false
t.isString();             // false
t.isNumber();             // false
t.isBoolean();            // false
t.isObject();             // false
t.isJdkType();            // true
t.isInterface();          // false
t.isAbstract();           // false
```

#### 泛型信息提取

```java
TypeEggg t = eggg.getTypeEggg(new HashMap<String, UserModel>() {}.getClass());

// 是否为参数化类型
t.isParameterizedType();  // true

// 获取 ParameterizedType
ParameterizedType pt = t.getParameterizedType();

// 获取实际泛型参数
Type[] args = t.getActualTypeArguments();
args[0]; // String.class
args[1]; // UserModel.class
```

#### 类型分类判断

Java 的类型体系包含多种形态，TypeEggg 对它们都提供了支持：

```java
// 参数化类型：List<String>、Map<String, Integer>
t.isParameterizedType();
t.getParameterizedType();
t.getActualTypeArguments();

// 类型变量：T、E 等
t.isTypeVariable();
t.getTypeVariable();

// 通配符类型：? extends Number、? super String
t.isWildcardType();
t.getWildcardType();

// 泛型数组类型：T[]、List<String>[]
t.isGenericArrayType();
t.getGenericArrayType();
```

#### 获取原始类型

```java
// 获取擦除后的 Class
Class<?> rawClass = t.getType();

// 获取原始 Type
Type originType = t.getOriginType();

// 获取泛型 Type
Type genericType = t.getGenericType();

// 获取泛型变量映射
Map<String, Type> genericInfo = t.getGenericInfo();
// 例如：{K=String, V=UserModel}
```

### 4、完整示例

```java
public class TypeMetadataDemo {
    private static final Eggg eggg = new Eggg();

    public static void main(String[] args) {
        // 示例 1：分析 Map 的泛型
        TypeEggg t1 = eggg.getTypeEggg(new HashMap<Integer, String>() {}.getClass());

        if (t1.isMap() && t1.isParameterizedType()) {
            Type keyType = t1.getActualTypeArguments()[0];    // Integer
            Type valueType = t1.getActualTypeArguments()[1];  // String
            System.out.println("Key: " + keyType + ", Value: " + valueType);
        }

        // 示例 2：分析 List 的泛型
        TypeEggg t2 = eggg.getTypeEggg(new ArrayList<UserModel>() {}.getClass());

        System.out.println(t2.isCollection());          // true
        System.out.println(t2.isList());                // true
        System.out.println(t2.getActualTypeArguments()[0]); // UserModel

        // 示例 3：分析普通类
        TypeEggg t3 = eggg.getTypeEggg(UserModel.class);

        System.out.println(t3.isJdkType());  // false
        System.out.println(t3.getType());    // UserModel.class
    }
}
```

### 5、TypeEggg API 速查

#### 类型判断方法

| 方法 | 返回值 | 说明 |
|---|---|---|
| `isCollection()` | `boolean` | 是否为 Collection 类型 |
| `isList()` | `boolean` | 是否为 List 类型 |
| `isSet()` | `boolean` | 是否为 Set 类型 |
| `isMap()` | `boolean` | 是否为 Map 类型 |
| `isArray()` | `boolean` | 是否为数组 |
| `isEnum()` | `boolean` | 是否为枚举 |
| `isPrimitive()` | `boolean` | 是否为基本类型 |
| `isString()` | `boolean` | 是否为 String |
| `isNumber()` | `boolean` | 是否为数字类型 |
| `isBoolean()` | `boolean` | 是否为布尔类型 |
| `isObject()` | `boolean` | 是否为 Object |
| `isJdkType()` | `boolean` | 是否为 JDK 内置类型 |
| `isInterface()` | `boolean` | 是否为接口 |
| `isAbstract()` | `boolean` | 是否为抽象类 |

#### 泛型分析方法

| 方法 | 返回值 | 说明 |
|---|---|---|
| `isParameterizedType()` | `boolean` | 是否为参数化类型 |
| `getParameterizedType()` | `ParameterizedType` | 获取参数化类型 |
| `getActualTypeArguments()` | `Type[]` | 获取实际泛型参数 |
| `isTypeVariable()` | `boolean` | 是否为类型变量 |
| `getTypeVariable()` | `TypeVariable` | 获取类型变量 |
| `isWildcardType()` | `boolean` | 是否为通配符类型 |
| `getWildcardType()` | `WildcardType` | 获取通配符类型 |
| `isGenericArrayType()` | `boolean` | 是否为泛型数组类型 |
| `getGenericArrayType()` | `GenericArrayType` | 获取泛型数组类型 |

#### 类型访问方法

| 方法 | 返回值 | 说明 |
|---|---|---|
| `getType()` | `Class<?>` | 擦除后的 Class |
| `getOriginType()` | `Type` | 原始 Type |
| `getGenericType()` | `Type` | 经过特化的泛型 Type |
| `getGenericInfo()` | `Map<String, Type>` | 泛型变量映射 |
| `getClassEggg()` | `ClassEggg` | 获取类元数据 |

### 6、补充说明

**匿名子类的作用**

Java 的泛型擦除是语言层面的设计，无法修改。但匿名子类有一个特性：编译器会在其父类签名中保留泛型参数信息。`new HashMap<String, Integer>() {}` 中的 `{}` 创建了一个匿名子类，泛型参数 `<String, Integer>` 会被记录在字节码中，供运行时读取。

**Type 和 Class 的区别**

`Class` 是 `Type` 的一种具体形态。`Type` 是更上层的概念，除了普通的 `Class`，还包括参数化类型 `ParameterizedType`、类型变量 `TypeVariable`、通配符 `WildcardType` 等。EggG 通过 TypeEggg 将这些类型统一封装。

**缓存机制**

TypeEggg 内部使用软引用（SoftReference）做缓存。同一类型多次调用 `getTypeEggg()` 时，解析只执行一次。内存紧张时缓存会自动释放。

