一、泛型类 (Generic Class)
定义:在类名后面加上<T>(可以是任意大写字母,如<E>、<K,V>)。
语法模板:
public class 类名 <T> { private T data; // 成员变量可以用 T public T getData() { // 方法返回值可以用 T return data; } public void setData(T data) { // 方法参数可以用 T this.data = data; } }你的Result就是一个典型的泛型类:
public class Result<T> { // 1. 这里声明了 <T>,代表整个类都可以用 T private Integer code; private String msg; private T data; // 2. 类内部直接使用 T // 3. 普通成员方法可以直接返回 T 或接收 T,不需要再声明 public T getData() { return data; } }二、泛型方法 (Generic Method)
定义:在方法返回值前面加上<T>(或其他字母)。这个方法可以独立于类的泛型存在。
关键点:即使类本身不是泛型类,方法也可以是泛型方法。如果类已经是泛型类,方法上的<T>会遮蔽(隐藏)类上的<T>,所以静态方法必须自己声明<T>。
1. 静态泛型方法(你的success方法)
// 静态方法不能访问类上的泛型参数,必须自己声明 public static <T> Result<T> success(T data) { // ↑ 这里的 <T> 是声明:我这是一个泛型方法,我要用到一个类型叫 T Result<T> result = new Result<>(); result.setData(data); return result; }解释:
public static <T> Result<T> success(T data)第一个
<T>是声明:告诉编译器,我要引入一个类型变量T。Result<T>是返回值类型。T data是参数类型。
2. 普通成员方法中的泛型方法
如果类已经定义了Result<T>,普通成员方法不需要再加<T>,可以直接用:
public class Result<T> { // ✅ 正确:不需要额外声明 <T>,直接用类的 T public T getData() { return data; } // ❌ 错误示例:多加了一个 <T> 会遮蔽类的 T,导致类型混乱 public <T> T getData() { // 这里的 T 是方法自己的 T,和类的 T 没有任何关系! } }三、代码速查表(结合你的Result)
| 位置 | 写法 | 含义 |
|---|---|---|
| 类定义 | public class Result<T> | 声明此类是一个泛型类,作用域为整个类 |
| 成员变量 | private T data; | 使用类上声明的T |
| 普通成员方法 | public T getData() | 直接使用类上的T,不需要写<T> |
| 静态方法 | public static <T> Result<T> success(T data) | 必须自己声明<T>,这个T与类的T无关 |
四、常见易错点对比
错误 1:静态方法直接使用类的T
public class Result<T> { // ❌ 编译错误:Non-static type variable T cannot be referenced from a static context public static Result<T> success() { return null; } }正确写法:
public static <T> Result<T> success() { return new Result<>(); }错误 2:成员方法多写了<T>
public class Result<T> { // ❌ 语法没错,但会导致类型擦除混乱,一般不这么写 public <T> T getData() { return (T) data; // 需要强制转换,丢失类型安全 } }错误 3:忘记写返回值前的泛型声明
// ❌ 如果类不是泛型类,这样写会报错 cannot resolve symbol T public Result<T> success(T data) { // ... }正确写法(类非泛型):
public <T> Result<T> success(T data) { // ... }五、一句话总结
| 场景 | 是否需要写<T> | 示例 |
|---|---|---|
| 定义泛型类 | 类名后写<T> | class Result<T> |
| 类成员变量/方法使用类泛型 | 不写 | T getData() |
| 静态方法想要用泛型 | 必须写 | static <T> Result<T> success(T data) |
| 普通方法想引入新的独立泛型 | 写(极不推荐) | <E> E convert(E e) |
记忆口诀:
类上有
<T>,成员不用写。静态想用泛,自己声明
<T>在前面。有参和无参构造器都是和普通的一样