跳转到主内容
极星编程网:以代码为星,赴技术山海!

java中的泛型指的是什么_参数化类型与编译期类型安全检查解析

泛型是编译期类型占位符,运行时被擦除;ArrayList不能赋值给ArrayList,因泛型具不变性,否则破坏类型安全。 泛型本质是编译期的类型占位符 Java 泛型不是运行时特性,而是编译器用来做类型约束的语法糖。它不改变 字节 码结构,也不会生成多个类版本(不像 C++ 模板)。你写
List
,底层实际还是
List
,只是编译器在编译阶段插入类型检查,并在必要时自动插入强制转换。 这意味着: - 运行时通过
obj.getClass()
拿不到泛型信息(类型擦除) - 不能用
new T()
或
T.class
—— 因为
T
在运行时已不存在 -
instanceof
不能用于参数化类型,比如
if (x instanceof List)
是 编译错误 ,只能写
if (x instanceof List)
为什么
ArrayList
不能赋值给
ArrayList
这是泛型「不变性」(invariance)的直接体现。尽管
String
是
Object
的子类,但
ArrayList
和
ArrayList
在类型系统中互不兼容——否则会破坏类型安全。 举个反例就明白: 如果允许
ArrayList strs = new ArrayList(); ArrayList objs = strs;
,那就能执行
objs.add(new Date())
,结果
strs
里混入了非
String
对象,后续遍历时
String s = strs.get(0)
就会抛
ClassCastException
。 要实现安全的向上转型,得用通配符: -
ArrayList extends Object>
可接收
ArrayList
(只读) -
ArrayList super String>
可接收
ArrayList
(可写入
String
)
Class
与泛型类的类型获取限制 泛型类如
class Box { ... }
在运行时无法获得
T
的具体类型,因为擦除后只剩原始类型
Box
。但有例外:当泛型类型信息被保留在类签名或父类继承链中时,可通过反射提取。 常见可行场景: - 子类继承泛型父类并固化类型:
class StringBox extends Box {}
→ 用
StringBox.class.getGenericSuperclass()
能拿到
Box
- 方法返回类型带泛型:
public List getNames() { ... }
→ 用
Method.getGenericReturnType()
可解析出
List
- 构造函数/字段声明含泛型:字段
private Map cache;
→
Field.getGenericType()
返回
Map
注意:这些只是「声明时的类型信息」,不代表运行时对象的真实内容类型,也不能靠它绕过擦除做实例化。 立即学习 “ Java免费学习笔记(深入) ”; Eclipse导入Android或其他的JAVA项目的正确方法 WORD版 本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载 泛型方法中的类型推断常被误用 泛型方法如
T pick(T a, T b)
的类型推断依赖实参,但推断规则有时反直觉。比如:
String s = pick("a", new Object()); // 编译失败:无法统一 T 为 String 和 Object
更隐蔽的问题出现在泛型方法 + 通配符组合时:
List nums = Arrays.asList(1, 2.0); Number n = max(nums); // 假设 max T max(Collection),这里会报错:? extends Number 不是具体类型
解决方式通常是显式指定类型参数:
Number n = Utils.max(nums);
,或改用更宽松的签名:
> T max(Collection)
。 真正容易被忽略的是:泛型方法的类型变量作用域仅限该方法,和类声明的
无关;二者同名也不代表同一类型。

相关文章