标签:win ring 编译器 规范 列表 派生 htm data 不能
不能用基本类型实例化类型参数
不能用类型参数代替基本类型:例如,没有Pair<double>,只有Pair<Double>,其原因是类型擦除。擦除之后,Pair类含有Object类型的域,而Object不能存储double值。这体现了Java语言中基本类型的独立状态。
运行时类型查询只适用于原始类型(raw type)
运行时:通常指在Classloader装载之后,JVM执行之时
类型查询:instanceof、getClass、强制类型转换
原始类型:即(raw type),泛型类型经编译器类型擦除后是Object或泛型参数的限定类型(例如Pair<T extends Comparable>,Comparable就是T的限定类型,转化后泛型的原始类型就是Comparable,所以Pair类不带泛型是Pair<Comparable>),即Pair类含有Comparable类型的域
JVM中没有泛型
eg:
if(a instanceof Pair<String>) //ERROR,仅测试了a是否是任意类型的一个Pair,会看到编译器ERROR警告
if(a instanceof Pair<T>) //ERROR
Pair<String> p = (Pair<String>) a;//WARNING,仅测试a是否是一个Pair
Pair<String> stringPair = ...;
Pair<Employee> employeePair = ...;
if(stringPair.getClass() == employeePair.getClass()) //会得到true,因为两次调用getClass都将返回Pair.class
不能创建参数化类型的数组(泛型数组)
参数化类型的数组:指类型带有泛型参数的数组,也即泛型数组,如Pair<T>[] 、 T[]
不能实例化参数化类型的数组,例如:
Pair<String> table = new Pair<String>[10]; //ERROR
在这里我们假设可以实例化,那么经编译器类型擦除后,table的类型是Pair[],我们再让它协变为Object[]:
Object[] objArray = table;
而一般来说,数组会记住他的元素类型Pair,我们如果试图存储其他类型的元素,就会抛出异常(数组存储检查),例如:
objArray[0] = "Hello"; //ERROR--component type is Pair
但是,对于泛型类型Pair<String>,类型擦除会使这种不同类检查机制无效,这就是不能实例化泛型数组的原因!
objArray[0] = new Pair<Employee>(); //如果泛型机制允许我们实例化数组,那么这一步就没理由出错了!而这违背了我们的初衷(限定类型)
泛型数组的间接实现:
通过泛型数组包装器,如ArrayList类,维护一个Object数组,然后通过进出口方法set、get来限定类型和强制转换数组类型,从而间接实现泛型数组,
例如:ArrayList: ArrayList<Pair<T>>、ArrayList<T>
不能实例化类型变量T
public static <T> Pair<T> makePair(Class<T> cl){
try{ return new Pair<>(cl.newInstance() , cl.newInstance()); }
catch(Exception ex) { return null; }
}
//这个方法可以按照下列方式调用:
Pair<String> p = Pair.makePair(String.class);
import java.lang.reflect.*;
...
public static <T extends Comparable> T[] minmax(T... a){
T[] mm = (T[]) Array.newInstance(a.getClass().getComponentType() , 2);
...
}
Class
。如果此类不表示数组类,则此方法返回 null。
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
【API文档描述】public static <T> T[] copyOf(T[] original,int newLength)
a
- 要存储列表元素的T[]数组(如果它足够大)否则分配一个具有相同运行时类型的新数组,返回该T[]数组@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a‘s runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass()); //a.getClass()得运行时目的数组的运行时类型
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
public static <T,U> T[] copyOf(U[] original,int newLength, Class<? extends T[]> newType)
泛型类的静态上下文中类型变量无效
public class Singleton<T>{
private static T singleInstance; //ERROR
public static T getSingleInstance(){...} //ERROR
}
不能throws或catch泛型类的实例(有关异常)
public static <T extends Throwable> void doWork(Class<T> t){
try{
do work
}catch (T e){ // ERROR
Logger.global.info(...)
}
}
public static <T extends Throwable> void doWork(T t) throws T { //此时可以throws T
try{
do work
}catch (Throwable realCause){ //捕获到具体实例
t.initCause(realCause);
throw t; //这时候抛具体实例,所以throw t 和 throws T 是可以的!
}
}
@SuppressWarnings("unchecked") //SuppressWarning标注很关键,使得编译器认为T是unchecked异常从而不强迫为每一个异常提供处理器
public static <T extends Throwable> void throwAs(Throwable e) throws T{ //因为泛型和类型擦除,可以传递任意checked异常,例如RuntimeException类异常
throw (T) e;
}
public abstract class Block{
public abstract void body() throws Exception;
public Thread toThread(){
return new Thread(){
public void run(){
try{
body();
}catch(Throwable t){
Block.<RuntimeException>throwAs(t);
}
}
};
}
@SuppressWarnings("unchecked")
public static <T extends Throwable> void throwAs(Throwable e) throws T{
throw (T) e ;
}
}
public class Test{
public static void main(String[] args){
new Block(){
public void body() throws Exception{
//不存在ixenos文件将产生IOException,checked异常!
Scanner in = new Scanner(new File("ixenos"));
while(in.hasNext())
System.out.println(in.next());
}
}.toThread().start();
}
}
注意擦除后的冲突
class Calender implements Comparable<Calender>{...}
class GGCalender extends Calender implements Comparable<GGCalender>{...} //ERROR
标签:win ring 编译器 规范 列表 派生 htm data 不能
原文地址:http://www.cnblogs.com/tiancai/p/7449207.html