泛型是java 5引入的编译期类型参数化机制,将类型作为参数传递,实现类、接口、方法对多种类型的适配,并把类型检查提前至编译时;其三种用法为泛型类(如box)、泛型接口(如generator)、泛型方法(如public void print(t... args));核心设计源于类型擦除,导致运行时无泛型信息,故禁止new t()、instanceof t等操作。

Java 泛型面试题答得准,关键不在背答案,而在讲清三点:它解决什么问题、怎么用、为什么这么设计。下面按高频考点拆解,直接对应面试真实提问场景。
泛型到底是什么?一句话说清
泛型是 Java 5 引入的编译期类型参数化机制——把类型当成参数传进去,让类、接口、方法能“适配多种类型”,同时把类型检查从运行时提前到编译时。不是语法糖,是类型安全的基石。
对比不写泛型:
- 没泛型:
List list = new ArrayList(); list.add("a"); int i = (Integer)list.get(0);—— 编译通过,运行时 ClassCastException - 有泛型:
List<string> list = new ArrayList(); list.add("a"); String s = list.get(0);</string>—— 编译就报错,不能 add(1),也不用强转
泛型的三种基本用法,必须会写例子
泛型类:类定义时带类型参数,如 Box<t></t>,字段、方法都可使用 T。
泛型接口:如 Comparator<t></t> 或自定义 Generator<t></t>,实现类可指定具体类型(StringGenerator implements Generator<string></string>)或继续泛型(NumberGenerator<t extends number></t>)。
泛型方法:方法签名前声明类型参数,如 public <t> void print(T... args)</t>。哪怕所在类不是泛型类,也能独立使用。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
注意:T、E、K、V 是约定俗成的占位符,不是关键字;> 是无界通配符,表示“某个确定但未知的类型”。
为什么不能 new T()?为什么不能用 instanceof 判断 T?
核心原因只有一个:类型擦除(Type Erasure)。泛型只在编译期存在,JVM 运行时所有泛型信息都被擦掉,List<string></string> 和 List<integer></integer> 都变成原始类型 List。
所以这些操作被禁止:
-
new T()→ 擦除后不知道 T 是什么类,无法实例化 -
if (obj instanceof T)→ 运行时 T 已不存在,无法判断 -
T[].class或new T[10]→ 数组需要运行时类型信息,擦除后无法保证类型安全 -
throw new T()或catch (T e)→ 异常类型必须在字节码中明确,擦除后不可行
替代方案:传 Class 对象,如 public <t> T create(Class<t> clazz)</t></t>。
通配符 ?、? extends T、? super T 怎么选?
这是泛型“读写一致性”的体现,记口诀:PECS(Producer Extends, Consumer Super)。
-
List extends Number>→ 只能取(Producer),取出来是 Number 或子类;不能 add(除了 null),因为不确定具体是 Integer 还是 Double -
List super Integer>→ 只能存(Consumer),可以 add(Integer);取出来只能当 Object,因为下界是 Integer,上界未知 -
List>→ 最宽泛,只能做 null 检查、size() 等与类型无关的操作
典型应用:Collections.copy(dest, src) 中,src 用 ? extends T,dest 用 ? super T,确保类型安全又灵活。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










