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
为什么会显示这样的变量行为?
答案 0 :(得分:1)
有关Java泛型的一些参考,请参阅Sun tutorial。
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);
<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_LIST
,String
还有其他什么?好吧,它是不可能定义的,因为静态存在独立于任何类实例。这就是为什么Integer
对他们来说是不可见的。
另一方面,使用具体泛型类型添加静态没有问题:
T