关于类型转换,静态和实例的泛型查询

时间:2012-09-09 15:53:01

标签: java generics

1)我想知道为什么泛型方法和类不接受超级关键字,尽管接受了扩展?

2)由于类型擦除,我们不能使用泛型的运算符实例,但为什么允许类型转换?

例如:

 if (objecta instanceof Object){} //doesn't work  
 Collection collection = new ArrayList();   
 Collection<Integer> d1 = (Collection<Integer>)collection; //works fine.  

根据我的理解,它不应该因为我们正在尝试将其强制转换为Collection,并且在运行时没有像Collection那样的东西。

3)我已经读过静态变量不能是泛型类的成员,但我不清楚为什么。为什么会显示以下行为?

 public class NoGenericss  
 { static List<Integer> list; //WORKS FINE  
 static List<T> list1; //COMPILATION ERROR   
 public class Genericss<T>  

 { static List<Integer> list; //WORKS FINE   
 static List<T> list1; //COMPILATION ERROR  
 static void meth(T t){} //COMPILATION ERROR  
 static <S> void meth(S t){} //WORKS FINE

为什么会显示这样的变量行为?

1 个答案:

答案 0 :(得分:1)

有关Java泛型的一些参考,请参阅Sun tutorial

2)

instanceof运算符是动态的,这意味着它会在运行时检查对象的类型。由于类型擦除,对象的通用类型(例如集合)在运行时不可用(List<Integer>List<String&gt;,List<URI>成为所有对象的List个。)

然而,演员表是静态的。 Java编译器检查变量的类型参数。如果你这样做:

List<Integer> ints = Arrays.asList(1, 2, 3);
List<String> strings = (List<String>) ints;

...编译器显示未经检查的警告,因为此操作是可行的,但不安全。因为现在你做的时候:

String s = ints.get(0);

您在运行时获得ClassCastException,因为VM会尝试将Integer投射到String

这是因为编译器将上面的泛型代码编译成以下代码的等价物。类型擦除以这种方式实现,因此所有通用参数都消失了,使得所有集合只有Object s的集合,因此,在必要时将强制转换插入到代码中。

List ints = Arrays.asList(1, 2, 3);
List strings = ints;
String s = (String) ints.get(0);

3)

<T>类型参数仅对成员字段和成员方法可见。泛型类的每个实例都可以有不同的T,例如,如果您有一个类:

class List<T> { // this is not java.util.List, just some custom class
    public List<T> subList(int start, int end) { ... }
    ...
}

...然后你可以这样做:

List<String> strings = ...
List<String> stringsSub = strings.subList(1, 2);

......还有:

List<Integer> ints = ...
List<Integer> intsSub = ints.subList(1, 2);

如您所见,第一个实例的T设置为String,第二个实例设置为Integer。因此,成员方法subList始终返回相同List的{​​{1}}。

现在,假设你添加了一个静态字段:

T

...在class List<T> { public static List<T> CONSTANT_LIST = ... ... } 的情况下,T会是什么? CONSTANT_LISTString还有其他什么?好吧,它是不可能定义的,因为静态存在独立于任何类实例。这就是为什么Integer对他们来说是不可见的。

另一方面,使用具体泛型类型添加静态没有问题:

T