Java泛型(3)泛型的限定
1.官方文档
https://docs.oracle.com/javase/tutorial/java/generics/restrictions.html
-
- Cannot Instantiate Generic Types with Primitive Types
- Cannot Create Instances of Type Parameters
- Cannot Declare Static Fields Whose Types are Type Parameters
- Cannot Use Casts or instanceof With Parameterized Types
- Cannot Create Arrays of Parameterized Types
- Cannot Create, Catch, or Throw Objects of Parameterized Types
- Cannot Overload a Method Where the Formal Parameter Types of Each Overload Erase to the Same Raw Type
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)。所以编译失败。