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
而这就是同一接口的不同参数化
相关文章推荐
- java泛型编程学习 笔记二:使用泛型的约束和局限性
- 【Java学习笔记】37:泛型使用时要注意的约束
- Java--泛型的约束和局限性
- Java 泛型 泛型的约束与局限性
- java中使用泛型类型的好处
- Java 理论与实践: 使用通配符简化泛型使用
- Java 理论与实践: 使用通配符简化泛型使用
- Java 理论与实践: 使用通配符简化泛型使用
- 使用Java程序的泛型应该注意的几个地方
- 使用 XSLT 和 Java 扩展验证 XML 文档中的复杂约束
- Java 5.0 泛型之 使用泛型统一传入的参数类型
- [转贴] Java 理论与实践: 使用通配符简化泛型使用
- Java中泛型使用的基本原则
- 泛型约束使用?有些不知道叫什么好!
- Java 理论与实践: 使用通配符简化泛型使用
- Java 理论与实践: 使用通配符简化泛型使用 (二)
- 泛型在Java中的使用方法
- Java 泛型使用(续)
- Java 理论和实践: 了解泛型(第一次使用泛型的用户的常见陷阱)
- Java 理论与实践: 使用通配符简化泛型使用