Question

keySet() returns java.util.Set. Why doesn't cast to NavigableSet throw a ClassCastException? This can be if real Object is a TreeSet with the java.util.Set reference. I can`t understand that.

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)+", ");
         }
     }
}
Was it helpful?

Solution

The best thing to do would be to look at actual code of TreeMap (this is from 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));
}

And here's the KeySet class declaration:

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

As you can see, TreeMap#keySet method returns a type Set which is a super interface of NavigableSet. And the Set reference returned from it points to a KeySet instance, as in navigableKeySet() method.

And since KeySet class implements NavigableSet, you can always cast a reference pointing to it's instance to a NavigableSet reference.

Just to make sure that you are independent of keySet() method implementation you could simply call navigableKeySet() method to get NavigableSet and avoid the cast

OTHER TIPS

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.

It doesn't through a ClassCastException because the returned object IS a NavigableSet. You can for example use the getClass() method on the returned object and print it. This class is either NavigableSet or a subclass of it.

You can also use a debugger (for example Eclipse) to get the class of an object.

Because the SortedMap.keySet() specification tells it returns a Set object, it may not be safe to cast it to NavigableSet. An other, or a change in, implementation may lead your code to through ClassCastException.

The compiler can't check for this and as a consequence the check is performed at run-time.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top