1

有人可以解释一下为什么这段代码编译和运行良好,尽管SortedSet是一个接口而不是一个具体的类:

public static void main(String[] args) {

    Integer[] nums = {4, 7, 8, 14, 45, 33};

    List<Integer> numList = Arrays.asList(nums);
    TreeSet<Integer> numSet = new TreeSet<Integer>();
    numSet.addAll(numList);

    SortedSet<Integer> sSet = numSet.subSet(5, 20);
    sSet.add(17);
    System.out.println(sSet);

}

它正常打印结果:[7, 8, 14, 17]

此外,SortedSet 无法实例化(预期)这一事实加剧了我的疑惑。此行不编译:

SortedSet<Integer> sSet = new SortedSet<Integer>();

但是,如果我尝试代码:

public static void main(String[] args) {

    Integer[] nums = {4, 7, 8, 14, 45, 33};

    List<Integer> numList = Arrays.asList(nums);
    numList.add(56);

    System.out.println(numList);
}

它抛出一个UnsupportedOperationException. 我认为,这是因为 List 是一个接口,不能作为一个具体的类来处理。什么是真实的SortedSet

4

4 回答 4

3

SortedSet 是一个接口。这意味着您可以引用实现此接口的类,但不能创建没有实现的类的实例。

在 Arrays.asList() 的情况下,它返回一个包装原始数组的类。您无法添加到原始数组,因此不支持添加。例如,如果您使用 set,您将更改原始数组。

于 2012-12-16T10:54:45.657 回答
1
List<Integer> numList = Arrays.asList(nums);

Array.asList()返回 一个数组,但包装在 List 接口中。所以列表仍然由数组支持,并且数组是固定大小的,你不能从数组中添加/删除元素。这就是为什么下一行会抛出异常UnsupportedOperationException

有关更多详细信息,javaArrayList仍然是一个数组,但它有一些帮助方法,用于删除/添加元素(您可以 wikiresizeable array获取更多详细信息。

其次,SortedSet是一个接口。抽象类之类的接口可以引用实现/扩展其的类,但它不是具体类,因此您不能在这些(接口或抽象类)上创建对象。

我明白了,你问的两个问题,可能都与polymorphismOOP 有关,我也建议你 wiki 这句话。

希望这有帮助:)

于 2012-12-16T10:55:57.793 回答
0

SortedSet 是一个接口而不是一个类。

您只能从非抽象类实例化。

List 也是一个接口。但是根据 List 的文档,方法“add”是可选的,这意味着不支持任何保证。

我认为可选方法与接口的想法和契约相矛盾。最好有一个 NonModifyableList(没有添加)和一个 ModifyableList(有添加)。当前糟糕的选择可能是历史的结果和不破坏旧代码的愿望。

于 2012-12-16T10:53:15.857 回答
0

如果我理解正确,您会问为什么可以成功地将对象称为 SortedSet(或任何接口类型)。当变量的类型是接口或抽象类时,这意味着该变量必须包含一个继承该变量类型的对象(或空对象)。

虽然每个对象的实际类型都必须是一个具体的类,但sSet变量只需要保存某个继承(实现)SortedSet 的类的实例。

在该TreeSet.subSet方法的情况下,它返回一个对象,其类型是内部定义的实现 SortedSet 的具体类。

于 2012-12-16T14:20:01.723 回答