

当泛型通过多层继承传递时，追踪泛型变量的实际类型是一项复杂的工作。EggG 通过 ClassEggg 和 FieldEggg 的配合，可以穿透多层继承链，还原每个字段的完整泛型类型。

### 1、问题场景

Java 的类型擦除会将泛型信息移除。对于单层泛型，可以通过匿名子类保留信息；但当泛型嵌套在多层继承中时，传统反射 API 无法追踪泛型变量的传导路径。

来看这个三层继承的例子：

```java
// 顶层类：定义泛型占位符 X 和 Y
class A<X, Y> {
    public X x;
    public Y y;
}

// 中间类：用 List<M> 替换 X，用 Map<String, N> 替换 Y
// 同时引入新的泛型占位符 M 和 N
class B<M, N> extends A<List<M>, Map<String, N>> {
    public M m;
    public N n;
}

// 具体类：将 M 确定为 String，将 N 确定为 Integer
class C extends B<String, Integer> {
}
```

**问题**：在类 `C` 中，字段 `x`、`y`、`m`、`n` 的实际类型分别是什么？

答案：
- `x` → `List<String>`
- `y` → `Map<String, Integer>`
- `m` → `String`
- `n` → `Integer`

传统反射 API 只能获取擦除后的类型（`Object`），EggG 能够还原这些泛型传导。

### 2、ClassEggg 概述

`ClassEggg` 是对 Java Class 的元数据封装，管理字段、方法、构造器和属性。通过 TypeEggg 获取：

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

ClassEggg classEggg = eggg.getTypeEggg(C.class).getClassEggg();
```

### 3、字段泛型追踪

#### 获取所有字段

```java
ClassEggg cw = eggg.getTypeEggg(C.class).getClassEggg();

// 获取所有字段，包括从父类继承的
Collection<FieldEggg> fields = cw.getAllFieldEgggs();
```

#### 按名称获取字段

```java
FieldEggg xField = cw.getFieldEgggByName("x");  // 从类 A 继承
FieldEggg yField = cw.getFieldEgggByName("y");  // 从类 A 继承
FieldEggg mField = cw.getFieldEgggByName("m");  // 从类 B 继承
FieldEggg nField = cw.getFieldEgggByName("n");  // 从类 B 继承
```

#### 追踪字段的泛型

```java
// 字段 x：经过传导后，实际类型是 List<String>
FieldEggg xField = cw.getFieldEgggByName("x");

xField.getType();                                    // List.class
xField.getTypeEggg().isParameterizedType();           // true
xField.getTypeEggg().getActualTypeArguments()[0];     // String.class

// 字段 y：经过传导后，实际类型是 Map<String, Integer>
FieldEggg yField = cw.getFieldEgggByName("y");

yField.getType();                                    // Map.class
yField.getTypeEggg().isParameterizedType();           // true
yField.getTypeEggg().getActualTypeArguments()[0];     // String.class
yField.getTypeEggg().getActualTypeArguments()[1];     // Integer.class

// 字段 m 和 n：传导后为简单类型
cw.getFieldEgggByName("m").getType();  // String.class
cw.getFieldEgggByName("n").getType();  // Integer.class
```

### 4、完整示例

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

    public static void main(String[] args) {
        ClassEggg cw = eggg.getTypeEggg(C.class).getClassEggg();

        // 遍历所有字段
        for (FieldEggg fe : cw.getAllFieldEgggs()) {
            Object digest = fe.getDigest();
            System.out.println(fe.getName() + " -> " + fe.getType() + " digest=" + digest);
        }

        // 验证字段 x 的泛型传导
        // A<X,Y> 中 X → List<M>，M → String，因此 x 是 List<String>
        assert cw.getFieldEgggByName("x").getType() == List.class;
        assert cw.getFieldEgggByName("x").getTypeEggg().isParameterizedType();
        assert cw.getFieldEgggByName("x").getTypeEggg().getActualTypeArguments()[0]
               == String.class;

        // 验证字段 y 的泛型传导
        // A<X,Y> 中 Y → Map<String,N>，N → Integer，因此 y 是 Map<String, Integer>
        assert cw.getFieldEgggByName("y").getType() == Map.class;
        assert cw.getFieldEgggByName("y").getTypeEggg().isParameterizedType();
        assert cw.getFieldEgggByName("y").getTypeEggg().getActualTypeArguments()[0]
               == String.class;
        assert cw.getFieldEgggByName("y").getTypeEggg().getActualTypeArguments()[1]
               == Integer.class;

        // 验证字段 m：B<M,N> 中 M → String
        assert cw.getFieldEgggByName("m").getType() == String.class;

        // 验证字段 n：B<M,N> 中 N → Integer
        assert cw.getFieldEgggByName("n").getType() == Integer.class;

        System.out.println("所有断言通过");
    }

    // 测试用的三层继承结构
    public static class A<X, Y> {
        public X x;
        public Y y;
    }

    public static class B<M, N> extends A<List<M>, Map<String, N>> {
        public M m;
        public N n;
    }

    public static class C extends B<String, Integer> {
    }
}
```

### 5、设计原理

EggG 的泛型传导分析采用逐层追踪策略：

1. **从子类向上追溯**：从具体类开始，逐层查看每一层将泛型变量映射成了什么类型。例如到 `B` 层发现 `X` 变成了 `List<M>`，再到 `C` 层发现 `M` 变成了 `String`。
2. **递归解析嵌套泛型**：对于带嵌套的泛型（如 `List<M>` 中还包含变量 `M`），继续向内解析，直到得到具体类型。
3. **结果缓存**：解析过的字段类型会被缓存，后续查询同一字段直接返回缓存结果。

### 6、ClassEggg 更多能力

#### 构造器

```java
// 获取所有构造器
List<ConstrEggg> constructors = cw.getConstrEgggs();

// 获取创造器（带 @Creator 注解的构造器或静态工厂方法）
ConstrEggg creator = cw.getCreator();

// 按参数类型查找构造器
ConstrEggg ctor = cw.findConstrEggg(String.class, int.class);

// 按可用键名匹配构造器（用于反序列化场景）
ConstrEggg matched = cw.matchConstrEggg(availableKeys, defaultCtor);
```

#### 方法

```java
// 获取公有方法
Collection<MethodEggg> publicMethods = cw.getPublicMethodEgggs();

// 获取声明方法
Collection<MethodEggg> declaredMethods = cw.getDeclaredMethodEgggs();

// 按名称和参数查找方法
MethodEggg method = cw.findMethodEggg("sayHello", String.class);
```

#### 属性

```java
// 获取所有属性（字段 + getter/setter 的组合）
Collection<PropertyEggg> properties = cw.getPropertyEgggs();

// 按名称获取属性
PropertyEggg prop = cw.getPropertyEgggByName("name");

// 按别名获取属性
PropertyEggg prop = cw.getPropertyEgggByAlias("userName");
```

#### Record 支持

```java
// 是否为 Java Record 类
cw.isRealRecordClass();

// 是否疑似 Record（字段全为 final，有全参构造器）
cw.isLikeRecordClass();
```

