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. 不能创建泛型数组实例

九、一句话记忆规则

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

相关推荐
aiopencode39 分钟前
Charles 抓不到包怎么办?HTTPS 抓包失败、TCP 数据流异常与底层补抓方案全解析
后端
稚辉君.MCA_P8_Java44 分钟前
Gemini永久会员 C++返回最长有效子串长度
开发语言·数据结构·c++·后端·算法
Penge6661 小时前
Redis-bgsave浅析
redis·后端
阿白的白日梦1 小时前
Windows下c/c++编译器MinGW-w64下载和安装
c语言·后端
Lear1 小时前
【SpringBoot】 文件下载功能完整实现指南
后端
用户2345267009821 小时前
Python中如何实现数据库连接池深度好文
后端
用户2345267009821 小时前
Python实现音频文件的分布式处理深度好文
后端
京东零售技术1 小时前
NeurIPS 2025 | TANDEM:基于双层优化的数据配比学习方法
后端·算法
沸腾_罗强1 小时前
Envoy方案实现分析报告
后端