您的位置:首页 > 编程语言 > Java开发

java泛型使用时的约束与局限性

2017-12-07 16:52 417 查看

不能使用基本类型实例化类型参数

运行时类型查询只适用于原始类型

java

if(a intanceof Pair<Stirng>) //ERROR


java

Pair<String> p = (Pair<String>) a; //Error


上面的2个例子在java中都是错误的

+ 类型查询只适用于原始类型

+ 参数化类型不能进行强制类型转换

不能创建参数化类型的数组

Pair<String>[] table = new Pair<String>[10];


在这只是不允许创建这个数组,但声明这个变量还是合法的

@Varargs警告

向参数个数可变的方法传递一个泛型类型的数组

public sttic <T> void addAll(Conllection<T> coll,T... TS){
for (t :ts){
coll.add(t);
}
}


下面是调用的状况

Collection<Pair<String>> talbe = ...;
Pair<String> pair1 = ...;
Pair<String> pair2 = ...;
addAll(table,pair1,pair2);


要调用这个方法的话,java虚拟机就必需建立一个Pair 数组,这就违反了规定,不过对于这种状况,规则有所放松,你只会得到一个警告

解决警告的方法有2中

1. 在包含addAll调用的方法增加标注@SuppessWarnings(“unchecked”)

2. 如果是java SE7 中可以直接在addAll上标注@SafeVarargs

java

@SafeVarargs

public static <T> void addAll(Collection<T> coll,T... ts)


不能实例化类型变量

不能使用new T(…) ,new T[…] 或者T。class这样的表达式中的类型就那个变量,下面的构造器方法就是错误的

public Pair() {
first = new T(); //error
second = new T(); //error
}


在这里类型擦除后T 将变成Object,而且本意不希望调用 new Object().但是可以通过反射调用Class.newInstance方法来构造泛型对象

+ 错误的调用方法

first = T.class.newInstance(); //ERROR


正确的调用方法

新建一个方法

public static <T> Pair<T> makePair(Class<T> cl){
try{
return new Pair<>(cl.newInstance(),cl.newInstance());
}catch(Excepiton ex){
return null;
}
}


2. 调用


Pair<String> p = Pair.makePair(String.clss);


Class本身就是泛型,而String.class是一个Class的一个实例,因此makePair能够推导出pair的类型

泛型类型的静态上下文中类型变量无效

不能在静态域或方法中引用类型变量

private static T singleTnstance; //ERROR

public static T getSingleInstance(){ //ERROR
if(singleInstance == null){
return singleInstance;
}
}


不能抛出或捕获泛型类的实例

既不能抛出也不能捕获泛型类对象.甚至泛型类型扩展Thtowable都是不合法的

public class Problem<T> extends Exception {/***/} //ERROR -- can't extend Thtowable


catch子居中不能使用类型变量如下面这个例子

public static <T extends Throwbale> void doWork(Class<T> t){
try{
do work
}catch(T e){
Logger.global.info(...)
}
}


但是在异常规范中使用类型变量是允许的.以下方法是合法的

public static <T extends Throwable> void doWork(T t) throws T{
try{
do work
}catch(Throwable realCause){
t.initCause(realCause)
throw t;
}
}


注意泛型擦除后的冲突

看下面这个例子

public class Pair<T>{
public boolean equals(T t){
return first.equals(value) && second.equals(value);
}
}


从概念上讲他有2个方法

boolean equals(String) //泛型的方法

boolean equals(Object) //Object超类的方法

这里类型擦除后我们认为就是

boolean equals(Object)

但是这里的会与Object类的equals冲突

泛型还有一个规则

要想支持类型擦除的转换,就需要强制限制一个类或类型变量不能同时成为两个接口类型的子类而这两个接口是同一接口的不同参数化

错误的例子

class Calendar implements Comparable<Calendar>{...}
class GregorianCalendar extends Calendar implements Comparable<GregorianCalendar>{...}


GregorianCalendar 会实现Comparable 和 Comparable

而这就是同一接口的不同参数化
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: