710 字
2 分钟
Java泛型编程详解
泛型刚出来的时候我觉得不就是个类型参数嘛,有啥好学的。后来被PECS原则(Producer Extends Consumer Super)绕晕了,才明白泛型的水有多深。这篇文章把我对泛型的理解整理了一遍,希望能帮你少走弯路。
Java泛型编程详解
什么是泛型?
泛型是Java 5引入的特性,允许在定义类、接口和方法时使用类型参数,实现代码复用和类型安全。在Java 5之前,从集合里拿东西都要强转,写起来又丑又不安全,泛型出来之后整个世界都清爽了。
基本语法
泛型类
public class Box<T> { private T value;
public void setValue(T value) { this.value = value; }
public T getValue() { return value; }}
// 使用Box<String> stringBox = new Box<>();stringBox.setValue("Hello");String value = stringBox.getValue();泛型方法
public class GenericMethod { public static <T> void printArray(T[] array) { for (T element : array) { System.out.print(element + " "); } }}类型参数命名约定
T:Type(类型)E:Element(元素,集合用)K、V:Key、Value(Map用)N:Number(数字)
通配符与边界
上界通配符 ? extends T
表示类型参数是T的子类或T本身。只能读取,不能写入(除了null)。
public static double sum(List<? extends Number> numbers) { double sum = 0.0; for (Number n : numbers) sum += n.doubleValue(); return sum;}// 可以传 List<Integer>、List<Double> 等下界通配符 ? super T
表示类型参数是T的父类或T本身。只能写入,读取时只能读到Object。
public static void addNumbers(List<? super Integer> list) { list.add(1); list.add(2);}// 可以传 List<Number>、List<Object> 等无界通配符 ?
表示任意类型,但只能读不能写(除了null)。
public static void printList(List<?> list) { for (Object element : list) { System.out.print(element + " "); }}PECS 原则
Producer Extends, Consumer Super——生产者用extends,消费者用super。
- 如果你要从集合中读取数据(生产者),用
? extends T - 如果你要向集合中写入数据(消费者),用
? super T - 如果既要读又要写,就别用通配符,直接用具体类型
这个原则是理解泛型通配符的核心,面试常考,建议背下来。
类型擦除
Java的泛型是编译时机制,运行时类型信息会被擦除。比如:
// 编译时Box<String> box = new Box<>();// 编译后(擦除后)Box box = new Box(); // 相当于原始类型类型擦除带来的限制:
- 不能创建泛型数组:
new List<String>[10]编译不过 - 不能使用instanceof检查泛型类型:
box instanceof Box<String>编译不过,只能box instanceof Box<?> - 不能使用基本类型作为类型参数:
Box<int>不行,要用Box<Integer> - 不能在静态上下文中使用类型参数
常用陷阱
- 原始类型——现在写代码看到没用泛型的集合,心里就发毛,因为永远不知道get出来的是什么类型
- 通配符用错——该用extends的地方用了super,编译不过
- 类型擦除的误解——运行时拿不到泛型类型信息,别指望用反射去获取
💡 实战贴士: 写工具类方法时,如果参数是集合且只读,用
? extends T;如果只写,用? super T。举个实际例子:Collections.sort(List<T> list)的签名是public static <T extends Comparable<? super T>> void sort(List<T> list),这里的? super T就是PECS的应用——因为Comparable是”消费”T的。
分享
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时
相关文章 智能推荐
1
Java网络编程详解
Java 用Java写一个简单的TCP聊天室是大学时最有成就感的事情之一。Socket编程虽然基础,但理解TCP/IP协议栈对排查网络问题帮助很大。
2
Java多线程编程详解
Java 多线程是Java面试的重灾区,synchronized、volatile、Lock的区别能聊一个小时。这篇文章从线程的创建到并发工具类,把多线程的知识点串了一遍。
3
Java面向对象编程基础详解
Java 封装、继承、多态——这三个词背了无数遍,但真正理解面向对象是在写了上万行代码之后的事。这篇文章用代码实例讲清楚OOP的核心概念。
4
Java注解详解
Java 刚学Java时觉得注解不就是几个@符号嘛,后来用Spring Boot才发现注解能玩出这么多花样——从编译检查到运行时注入,注解远不止看起来那么简单。
5
Java NIO详解
Java NIO的Selector模型让我第一次感受到了单线程处理万级连接的魅力。相比传统IO的阻塞读写,Channel加Buffer的组合简直是为高性能网络编程量身定做。






