java遗珠之泛型七大限制
Posted 吴冬冬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java遗珠之泛型七大限制相关的知识,希望对你有一定的参考价值。
不能使用原始类型实例化泛型类型
参数化类型如下:
public class OrderedPair<K, V> implements Pair<K, V>
private K key;
private V value;
public OrderedPair(K key, V value)
this.key = key;
this.value = value;
public K getKey()
return key;
public V getValue()
return value;
public void setKey(K key)
this.key = key;
public void setValue(V value)
this.value = value;
不能用原始类型代替K和V
OrderedPair<int, char> p1 = new OrderedPair<>(1, 'a'); // compile-time error
仅仅非原始类型允许替代
OrderedPair<Integer, Character> p1 = new OrderedPair<>(1, 'a');
注意后面只是进行了自动封包
不能创建类型参数的实例
不能创建类型参数的实例,会产生编译错误
public static <E> void append(List<E> list)
E elem = new E(); // compile-time error
list.add(elem);
变通一下,可以通过反射来实现目的
public static <E> void append(List<E> list,Class<E> eClass) throws IllegalAccessException, InstantiationException
E elem = eClass.newInstance(); // compile-time error
list.add(elem);
可以如下调用
public static void main(String[] args)
List<String> strings=new ArrayList<>();
try
append(strings,String.class);
catch (IllegalAccessException e)
e.printStackTrace();
catch (InstantiationException e)
e.printStackTrace();
不能定义类型为类型参数的静态字段
类的静态变量是所以非静态对象共享的,因此类型参数的静态字段是禁止的,比如:
public class MobileDevice<T>
private static T os;
// ...
如果允许,想象一下下面的代码
MobileDevice<Smartphone> phone = new MobileDevice<>();
MobileDevice<Pager> pager = new MobileDevice<>();
MobileDevice<TabletPC> pc = new MobileDevice<>();
是不是彻底不知道T到底是啥了。
不能在参数化类型上使用强制转换和instanceof
因为编译器会擦除泛型代码的所有类型参数,你不能证实在运行时泛型类型的参数类型到底是什么
public static <E> void rtti(List<E> list)
if (list instanceof ArrayList<Integer>) // compile-time error
// ...
参数化类型在运行传入到方法中
S = ArrayList<Integer>, ArrayList<String> LinkedList<Character>, ...
运行时无法追踪参数类型,它不知道ArrayList<Integer>
和ArrayList<String>
有啥区别。
最多能确定无边界的通配符是个ArrayList
,比如:
public static void rtti(List<?> list)
if (list instanceof ArrayList<?>) // OK; instanceof requires a reifiable type
// ...
同样,你也不能做类型转换,除非是无边界通配符的参数化类型。
List<Integer> li = new ArrayList<>();
List<Number> ln = (List<Number>) li; // compile-time error
但是还有一些情况下,编译器知道怎么转换:
List<String> l1 = new ArrayList<>();
ArrayList<String> l2 = (ArrayList<String>)l1; // OK
不能创建参数化类型的数组
不能创建参数化类型的数组,下面代码编译不过
List<Integer>[] arrayOfLists = new List<Integer>[2]; // compile-time error
下面的代码很明显会运行异常
Object[] strings = new String[2];
strings[0] = "hi"; // OK
strings[1] = 100; // An ArrayStoreException is thrown.
创建参数化类型其实和上面的代码是类似的
Object[] stringLists = new List<String>[]; // compiler error, but pretend it's allowed
stringLists[0] = new ArrayList<String>(); // OK
stringLists[1] = new ArrayList<Integer>(); // An ArrayStoreException should be thrown,
// but the runtime can't detect it.
不能创建,捕获或抛出参数化类型的对象
泛型不能直接或间接扩展Throwable
,下面的例子都会编译错误
// Extends Throwable indirectly
class MathException<T> extends Exception /* ... */ // compile-time error
// Extends Throwable directly
class QueueFullException<T> extends Throwable /* ... */ // compile-time error
方法也不能catch类型参数的实例
public static <T extends Exception, J> void execute(List<J> jobs)
try
for (J job : jobs)
// ...
catch (T e) // compile-time error
// ...
但是可以通过类型参数抛出异常
class Parser<T extends Exception>
public void parse(File file) throws T // OK
// ...
不能重载类型擦除后原生类型相同的方法
擦除后参数签名就一样了,自然不能重载
public class Example
public void print(Set<String> strSet)
public void print(Set<Integer> intSet)
以上是关于java遗珠之泛型七大限制的主要内容,如果未能解决你的问题,请参考以下文章