【发布时间】:2015-07-29 22:42:57
【问题描述】:
除了标准的构造函数之外,TreeSet 的构造函数还包括一个允许您提供 Comparator 的构造函数和一个允许您从另一个 SortedSet 创建的构造函数:
TreeSet(Comparator<? super E> c) // construct an empty set which will be sorted using the // specified comparator TreeSet(SortedSet<E> s) // construct a new set containing the elements of the // supplied set, sorted according to the same ordering其中的第二个在其声明中与标准的“转换构造函数”太接近了:
TreeSet(Collection<? extends E> c)正如 Joshua Bloch 在 Effective Java(方法一章中的“明智地使用重载”项)中解释的那样,调用两个采用相关类型参数的构造函数或方法重载之一可能会产生令人困惑的结果。这是因为,在 Java 中,对重载的构造函数和方法的调用是在编译时根据参数的静态类型解析的,因此对参数应用强制转换会对调用的结果产生很大的影响,因为以下代码显示:
// construct and populate a NavigableSet whose iterator returns its // elements in the reverse of natural order: NavigableSet<String> base = new TreeSet<String>(Collections.reverseOrder()); Collections.addAll(base, "b", "a", "c"); // call the two different constructors for TreeSet, supplying the // set just constructed, but with different static types: NavigableSet<String> sortedSet1 = new TreeSet<String>((Set<String>)base); NavigableSet<String> sortedSet2 = new TreeSet<String>(base); // and the two sets have different iteration orders: List<String> forward = new ArrayList<String>(); forward.addAll(sortedSet1); List<String> backward = new ArrayList<String>(); backward.addAll(sortedSet2); assert !forward.equals(backward); Collections.reverse(forward); assert forward.equals(backward);这个问题困扰着框架中所有排序集合(TreeSet、TreeMap、ConcurrentSkipListSet 和 ConcurrentSkipListMap)的构造函数。为避免在您自己的类设计中出现这种情况,请为不同的重载选择参数类型,以便适合某个重载的类型的参数不能转换为适合不同重载的类型。如果这不可能,则应将两个重载设计为具有相同参数的行为相同,而不管其静态类型如何。例如,从集合构造的 PriorityQueue 使用原始的排序,无论为构造函数提供的静态类型是包含比较器的类型 PriorityQueue 或 SortedSet 之一,还是只是一个普通的 Collection。为了实现这一点,转换构造函数使用提供的集合的 Comparator,只有在没有自然排序时才回退到自然排序。
目前在看《Java Generics and Collections》这本书,上面是我看不懂的[page185~186]。
首先,我不太明白它为什么使用这个例子,以及它想要说明什么。
其次,我不太了解“转换构造函数”的概念。是不是因为有转换构造函数的存在,才应该慎重使用重载呢?
【问题讨论】:
-
日食错误是什么?
-
这是为我编译的。你的编译器应该得到这个构造函数docs.oracle.com/javase/8/docs/api/java/util/TreeSet.html
-
@kervin 是的,它现在为我编译,抱歉我没有导入 set 包。已更新问题
标签: java data-structures collections constructor overloading