1

keySet() 返回 java.util.Set。为什么不强制转换为 NavigableSet 抛出 ClassCastException?如果真正的 Object 是带有 java.util.Set 引用的 TreeSet,则可能是这样。我无法理解。

import java.util.*;
class A1{}
public class Main{
     public static void main(String args[]){
         SortedMap nvs=new TreeMap();
         nvs.put(1,"one");
         nvs.put(2,"two");
         nvs.put(3,"three");
         nvs.put(4,"four");
         NavigableSet nss=(NavigableSet)nvs.keySet();
         for(Object ob: nss){
              System.out.print(nvs.get(ob)+", ");
         }
     }
}
4

3 回答 3

2

最好的办法是查看实际代码TreeMap(来自 java 1.7):

public Set<K> keySet() {
    return navigableKeySet();
}

public NavigableSet<K> navigableKeySet() {
    KeySet<K> nks = navigableKeySet;
    return (nks != null) ? nks : (navigableKeySet = new KeySet(this));
}

这是KeySet类声明:

static final class KeySet<E> extends AbstractSet<E> implements NavigableSet<E> {...}

如您所见,TreeMap#keySet方法返回一个类型Set,它是NavigableSet. 并且Set从它返回的引用指向一个KeySet实例,就像在navigableKeySet()方法中一样。

而且由于KeySet类 implements NavigableSet,您始终可以将指向它的实例的引用转换为NavigableSet引用。

只是为了确保您独立于keySet()方法实现,您可以简单地调用navigableKeySet()方法来获取NavigableSet并避免强制转换

于 2012-12-07T20:04:42.453 回答
2

Your question shows that you don't understand polymorphism. Let's use an analogy. You go to a bar, and ask for a beer. And you get a Stella. You didn't ask specifically for a Stella, and the bar didn't make it public that their beers were actually Stella beers, but the fact is that the actual, concrete type of beer you got was a Stella. Since the bar doesn't guarantee that you'll get a Stella when you ask for a beer, you shouldn't rely on it, because a future version of the bar could give you a Jupiler instead., since both Jupiler and Stella are beers.

It's the same with your question. The return type is Set, so it could return any kind of Set. And unless the javadoc guarantees that the method in fact returns a NavigableSet, you shouldn't rely on it.

于 2012-12-07T20:11:24.740 回答
0

它没有通过 a ClassCastException,因为返回的对象是 a NavigableSet。例如,您可以在返回的对象上使用 getClass() 方法并打印它。这个类要么是它,要么NavigableSet是它的子类。

您还可以使用调试器(例如 Eclipse)来获取对象的类。

因为SortedMap.keySet()规范告诉它返回一个Set对象,所以将它强制转换为NavigableSet. 另一个或更改的实现可能会导致您的代码通过ClassCastException.

编译器无法检查这一点,因此检查是在运行时执行的。

于 2012-12-07T19:59:19.297 回答