Java泛型(3)泛型的限定

1.官方文档

https://docs.oracle.com/javase/tutorial/java/generics/restrictions.html

2.不可构造泛型形参对象

2.1 限制

public static <E> void append(List<E> list) {
E elem = new E(); // compile-time error
list.add(elem);
}

2.2 补偿方法

可以通过反射构造泛型形参对象.

public static <E> void append(List<E> list, Class<E> cls) throws Exception {
E elem = cls.newInstance(); // OK
list.add(elem);
}
public static void test(){
List<String> ls = new ArrayList<>();
append(ls, String.class);
}

3.基本类型不可作泛型形参

Pair<int, char> p = new Pair<>(8, 'a'); // compile-time error

4.泛型形参不能声明成static

public class MobileDevice<T> {
private static T os;
// ...
}

原因是无法确定os具体是什么类型,可能是Smartphone,Pager,TabletPC中的一种.

MobileDevice<Smartphone> phone = new MobileDevice<>();
MobileDevice<Pager> pager = new MobileDevice<>();
MobileDevice<TabletPC> pc = new MobileDevice<>();

5.参数化类型无法使用 instanceof运算符和强转

5.1 无法用instanceof具体类型

public static <E> void rtti(List<E> list) {
if (list instanceof ArrayList<Integer>) { // compile-time error
// ...
}
}

5.2 可以instanceof  ?通配符

public static void rtti(List<?> list) {
if (list instanceof ArrayList<?>) { // OK; instanceof requires a reifiable type
// ...
}
}

6.未限定泛型实参时,类型强传时有限制

6.1 泛型类型相同,泛型实参为父子,不可

List<Integer> li = new ArrayList<>();
List<Number> ln = (List<Number>) li; // compile-time error

6.2 泛型类型为父子,泛型实参相同,可以

List<String> l1 = ...;
ArrayList<String> l2 = (ArrayList<String>)l1; // OK

7.参数化类型不可为数组

List<Integer>[] arrayOfLists = new List<Integer>[2]; // compile-time error

8.参数化类型不能当异常类型

8.1 不可直接继承Excetpion、Throwable

// Extends Throwable indirectly
class MathException<T> extends Exception { /* ... */ } // compile-time error
// Extends Throwable directly
class QueueFullException<T> extends Throwable { /* ... */ // compile-time error

8.2 泛型形参不用作catch语句

public static <T extends Exception, J> void execute(List<J> jobs) {
try {
for (J job : jobs)
// ...
} catch (T e) { // compile-time error
// ...
}
}

8.3 泛型形参可 extends Exception

class Parser<T extends Exception> {
public void parse(File file) throws T { // OK
// ...
}
}

9.参数化类型不参与函数重载

public class Example {
public void print(Set<String> strSet) { }
public void print(Set<Integer> intSet) { }
}

这两个函数不算重载,它们被擦除后生成相同的函数public void print(Object strSet)。所以编译失败。

 

posted @   f9q  阅读(367)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示