通配符,java中的通用

时间:2012-06-20 02:30:45

标签: java generics

我在countList方法上遇到编译时错误。

public static void countList( List<? extends Number> list, int count ){
        for( int i = 0; i < count; i++ ){
            list.set(i, i-1);
        }
}

public static void clearList( List<?extends Number> list){
    list.clear();
}

它说: 类型List中的方法set(int,capture#2-of?extends Number)不适用于参数(int,int)

此错误消息是什么意思?为什么我不能在列表中设置元素?为什么清除列表是可以的?

2 个答案:

答案 0 :(得分:3)

因为这是一个“扩展数字的东西,但我不知道是什么。”你不能只把整数放在那里,如果它实际上是一个双打列表怎么办?

List<Double> list = new ArrayList<Double>();
list.add(Double.valueOf(4.5);
countList(list, 1);
Double d = list.get(0); //what happens here?  You put an Integer in there!  class cast exception

您可以清除列表,因为对于该操作,Number中的哪个子类型实际上并不重要。清楚明确是清楚的。

答案 1 :(得分:2)

问题是由于类型擦除,编译器不知道在运行时将列表中的 type 添加到列表中。考虑这个例子:

public static void main(String[] args) {
        List<Integer> intList= new ArrayList<Integer>();
        // add some Integers to the list here
        countList(intList, 4);

}

public static void countList( List<? extends Number> list, int count ) {
        for( double d = 0.0; d < count; d++ ){
            list.set((int)d, d-1); // problem at d-1, because at runtime, 
            // the double result of d-1 will be autoboxed to a Double, 
            // and now you have added a Double to an Integer List (yikes!);
        }
}

因此,您永远不能使用? extends SomeObject语法添加到通用类型的集合。如果必须添加,可以将方法声明更改为:

  1. 将方法声明更改为public static void countList( List<Number> list, int count )
  2. 将方法更改为public static void countList( List<? super Integer> list, int count )
  3. 无论哪种方式,编译器都会停止抱怨,因为它可以放心,你永远不会在List中添加任何与List声明的类型不同的东西。