泛型是Java SE中比较复杂的内容了,而擦除和转型又是泛型中比较复杂的内容,这里总结了泛型关于转型的一些知识,其中还涉及到了一点擦除。
public class myFixed {
public static void main(String[] args) {
Fixed<String> stringFixed = new Fixed<>();
stringFixed.push("abc");
stringFixed.push("abc1");
stringFixed.push(123);
stringFixed.push(456);
Object obj1 = stringFixed.<String>pop();
System.out.println(obj1.getClass() + " " + obj1);
Integer i =(Integer) obj1;
System.out.println(i.getClass().toString() + " " + i);
String obj = stringFixed.pop();
System.out.println(obj.getClass().toString() + " " + obj);
// obj = stringFixed.pop();
// System.out.println(obj.getClass().toString() + " " + obj);
// obj = stringFixed.pop();
// System.out.println(obj.getClass().toString() + " " + obj);
}
static class Fixed<T> {
Object[] objects = new Object[10];
int index = 0;
void push(Object object){
objects[index++] = object;
}
@SuppressWarnings("unchecked")
T pop(){
Object obj = objects[--index];
T t =(T) obj;
return t;
}
}
}
在代码29行中实际上并没有发生转型,因为在编译的时候T就会被擦除了,所以编译器无法知道这个转型是否安全,所以会产生“unchecked cast”警告,通过@SuppressWarnings(“unchecked”)注解消除警告;并且由于擦除T在运行时相当于Object,所以这里实际上只是将Object转型为Object。实际上的转型发生在11行和13行这样的情况。String obj = stringFixed.pop();pop()返回的是Object,这里自动发生强转。此时从 int 到 string 强转失败,会崩溃。处理方式如下:
Object obj1 = stringFixed.pop();
System.out.println(obj1.getClass() + " " + obj1);
Integer i =(Integer) obj1;
stringFixed的泛型类型参数是String,pop传递回来了一个String的伪装,所以Integer obj1 = stringFixed.pop();编译不会通过,尽管pop()事实返回的是一个Object类型(运行时类型为Integer);所以用String接收编译能通过,但是运行会崩溃(当pop()运行时返回的是String类型时就正常运行);正确做法应该用Object接收返回结果,然后在强转为运行时返回的类型。