Collections类中checkedList方法的用途

时间:2015-04-01 10:23:21

标签: java generics

api说"返回指定集合的​​动态类型安全视图" 但是当泛型可以在编译时检测到是否有任何可疑内容被插入到集合中时,它仍然需要它。

文档说"语言中的泛型机制提供了编译时(静态)类型检查,但是可以通过未经检查的强制转换来破坏这种机制"

但即使这样也不行[/ p>

List<Integer> list = new ArrayList<Integer>();
Object o = new Float(1.2);
Integer i = (Integer)o; // line3
list.add(i);

但即使这一个wud在运行时失败,并且在第3行抛出ClassCastException,因为o实际上拥有Float,无法将其转换为Integer。所以,我想知道如何围绕静态编译时泛型检查来证明checkList方法的存在

2 个答案:

答案 0 :(得分:7)

这可以通过不使用泛型来完成,如果您使用的库是使用没有泛型的Java版本的,那么可以这样做。

以下代码是如何使用泛型执行此操作的示例:

List<Integer> list = new ArrayList<Integer>();
List unsafeList = list; // Cast to a list that is not using generics
Object o = new Float(1.2);
unsafeList.add(o);
// list now contains a non Integer object.

这确实会生成多个警告,但如果您愿意,您当然可以忽略这些警告。

答案 1 :(得分:0)

你说得对,当使用检查类型列表(泛型)和 当您知道您的列表需要一个 int 时,尝试添加一个 Float 是很荒谬的。

当文档说“可以通过未经检查的强制转换来击败这种机制。”,它不会处理您明显不允许的强制转换。它处理该代码:

List list = new ArrayList<>();
Integer i = 3;
Object o = new Float(1.2);
Float f = new Float(2.1);
list.add(i); // warning
list.add(o); // warning
list.add(f); // warning
// list contains [3, 1.2, 2.1]

然后,它说“通常这不是问题,因为编译器会针对所有此类未经检查的操作发出警告。”,这就是您的 IDE 发出警告的原因。这是合法的,它有效但没有意义。

最后,文档说“...仅靠类型检查是不够的。例如,假设将集合传递给第三方库...”因为您可以使用类型已检查集合(以保证您这边的类型)并将其传递给接受未检查集合的库。糟糕的事情在这里发生,库可以执行我们看到的合法且有效的错误代码:

public class Library {
  public void addNumbers(List list) { // unchecked type
    list.add("5");
    list.add(Duration.ofMinutes(6));
  }
}

public static void main( String[] args ) {
    Library library = new Library();
    List<Integer> list = new ArrayList<>(); // checked type
    Integer i1 = 3;
    Integer i2 = 4;
    list.add(i1);
    list.add(i2);
    library.addNumbers(list);
    // list contains [3, 4, 5, PT6M]
}

为了避免第三方添加错误的类型值,您必须传递一个 uncheckedList...

public class Library {
  public void addNumbers(List list) {
    list.add("5");
    list.add(Duration.ofMinutes(6));
  }
}
public static void main( String[] args ) {
    Library library = new Library();
    List<Integer> list = new ArrayList<>();
    Integer i1 = 3;
    Integer i2 = 4;
    list.add(i1);
    list.add(i2);
    List<Integer> checkedList = Collections.checkedList(list, Integer.class);
    library.addNumbers(checkedList); // ClassCastException
}

请注意,如果您向checkedList 添加值,您的初始列表将被填充...