Java 泛型支持的类型

一、一句话总结

泛型类型参数可以是:类、接口、数组,不能是:基本类型、具体值、实例

二、允许的类型

1. 类和接口

java 复制代码
// ✅ 引用类型都可以
class Box<T> {}  // T可以是任何引用类型

Box<String> stringBox;         // 类
Box<Integer> integerBox;       // 包装类
Box<List<String>> listBox;     // 泛型类
Box<Comparable> compBox;       // 接口
Box<Runnable> runnableBox;     // 函数式接口

2. 通配符类型

java 复制代码
// ? 表示未知类型
List<?> wildcardList;          // 任意类型
List<? extends Number> nums;   // Number或其子类
List<? super Integer> ints;    // Integer或其父类

3. 泛型数组

java 复制代码
// 可以声明泛型数组引用
T[] array;                      // ✅ 可以声明
// T[] arr = new T[10];         // ❌ 不能创建实例

4. 嵌套泛型

java 复制代码
// 多层嵌套
Map<String, List<Integer>> map;                // Map的value是List
List<Map.Entry<String, Integer>> entries;      // List的元素是Map.Entry
Box<Pair<String, Integer>> box;                // 复杂嵌套

三、不允许的类型

1. 基本类型(最重要的限制)

java 复制代码
// ❌ 不能使用基本类型
Box<int> intBox;               // 编译错误!
Box<double> doubleBox;         // 编译错误!
Box<char> charBox;             // 编译错误!

// ✅ 必须使用包装类
Box<Integer> intBox;           // 正确
Box<Double> doubleBox;         // 正确
Box<Character> charBox;        // 正确

2. 原始类型(不建议,但允许)

java 复制代码
// ⚠️ 原始类型(raw type)- 已过时
Box rawBox = new Box();        // 警告:未指定泛型类型
Box<String> stringBox = new Box();  // ✅ 应该这样

3. 具体值/实例

java 复制代码
// ❌ 不能是具体值
class Box<"string"> {}         // 错误
class Box<new String()> {}     // 错误
class Box<10> {}               // 错误

4. 静态上下文

java 复制代码
class Box<T> {
    // ❌ 不能有静态泛型字段
    static T staticField;       // 编译错误
    
    // ❌ 静态方法不能使用类的类型参数
    static T staticMethod() {   // 编译错误
        return null;
    }
    
    // ✅ 静态方法可以有自己独立的泛型参数
    static <U> U genericMethod(U param) {
        return param;
    }
}

四、边界限制

1. 类型边界

java 复制代码
// 只能扩展类或实现接口,不能是其他
class Box<T extends Number & Comparable<T>> {  // ✅ 正确
    // T必须是Number的子类且实现Comparable
}

// ❌ 错误边界
class Box<T super String> {}    // 不能使用super
class Box<T extends 100> {}     // 不能是具体值

2. 多重边界

java 复制代码
// 最多一个类,多个接口
class Container<T extends Number & Comparable<T> & Serializable> {
    // T必须:继承Number,实现Comparable和Serializable
    // 注意:类必须在前,接口在后
}

五、实际使用中的类型

1. 集合框架(最常用)

java 复制代码
List<String> strings = new ArrayList<>();      // 列表
Set<Integer> numbers = new HashSet<>();        // 集合
Map<String, Integer> scores = new HashMap<>(); // 映射
Queue<Double> queue = new LinkedList<>();      // 队列

2. 自定义数据结构

java 复制代码
// 节点类
class Node<T> {
    T data;
    Node<T> next;
    
    Node(T data) {
        this.data = data;
    }
}

// 二叉树
class TreeNode<T extends Comparable<T>> {
    T value;
    TreeNode<T> left;
    TreeNode<T> right;
}

3. 函数式接口

java 复制代码
// 带泛型的函数式接口
@FunctionalInterface
interface Transformer<T, R> {
    R transform(T input);
}

// 使用
Transformer<String, Integer> lengthGetter = String::length;
Transformer<Integer, String> stringConverter = Object::toString;

六、类型推断(钻石运算符)

1. 自动类型推断

java 复制代码
// Java 7+ 钻石运算符
List<String> list = new ArrayList<>();      // ✅ 自动推断为<String>

// Java 7之前
List<String> list = new ArrayList<String>(); // ✅ 老写法

// 嵌套泛型也能推断
Map<String, List<Integer>> map = new HashMap<>();

2. 方法类型推断

java 复制代码
// 方法调用时自动推断
<T> T getDefault(Class<T> clazz) { ... }

String str = getDefault(String.class);      // T推断为String
Integer num = getDefault(Integer.class);    // T推断为Integer

七、特殊限制及解决方案

1. 基本类型的解决方案

java 复制代码
// 问题:不能直接用int
// Box<int> box;  // ❌ 错误

// 解决方案1:使用包装类
Box<Integer> intBox = new Box<>();

// 解决方案2:使用特化版本(第三方库如fastutil)
// IntBox, LongBox等专用容器

// 解决方案3:Java未来可能支持(Valhalla项目)

2. 类型擦除的影响

java 复制代码
// 运行时类型信息丢失
Box<String> stringBox = new Box<>();
Box<Integer> integerBox = new Box<>();

// 运行时都是Box<Object>
System.out.println(stringBox.getClass() == integerBox.getClass()); // true

// 解决方案:传递Class对象
class Box<T> {
    private Class<T> type;  // 保存类型信息
    Box(Class<T> type) {
        this.type = type;
    }
}

八、检查清单

✅ 可以用作泛型参数:

  1. 任何引用类型(类、接口)
  2. 其他泛型类型(List<String>
  3. 通配符(?, ? extends T, ? super T
  4. 数组类型(作为声明)

❌ 不能用作泛型参数:

  1. 基本类型(int, double, char等)
  2. 具体值或实例
  3. 原始类型(应避免)
  4. 在静态上下文中使用类的类型参数

⚠️ 需要注意:

  1. 多重边界时类在前,接口在后
  2. 类型擦除导致运行时类型信息丢失
  3. 不能创建泛型数组实例

九、一句话记忆规则

泛型类型参数 = 任何引用类型 + 通配符,但不能是基本类型或具体值,静态上下文有限制。

相关推荐
开心就好202511 小时前
不同阶段的 iOS 应用混淆工具怎么组合使用,源码混淆、IPA混淆
后端·ios
架构师沉默11 小时前
程序员如何避免猝死?
java·后端·架构
椰奶燕麦11 小时前
Windows PackageManager (winget) 核心故障排错与通用修复指南
后端
zjjsctcdl12 小时前
springBoot发布https服务及调用
spring boot·后端·https
zdl68612 小时前
Spring Boot文件上传
java·spring boot·后端
世界哪有真情13 小时前
哇!绝了!原来这么简单!我的 Java 项目代码终于被 “拯救” 了!
java·后端
RMB Player13 小时前
Spring Boot 集成飞书推送超详细教程:文本消息、签名校验、封装工具类一篇搞定
java·网络·spring boot·后端·spring·飞书
重庆小透明13 小时前
【搞定面试之mysql】第三篇 mysql的锁
java·后端·mysql·面试·职场和发展
武超杰13 小时前
Spring Boot入门教程
java·spring boot·后端
IT 行者14 小时前
Spring Boot 集成 JavaMail 163邮箱配置详解
java·spring boot·后端