wood burning stoves 2.0*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Why do we get(Object key) for interface Map<K,V>? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Why do we get(Object key) for interface Map<K,V>?" Watch "Why do we get(Object key) for interface Map<K,V>?" New topic
Author

Why do we get(Object key) for interface Map<K,V>?

Leon Omk
Ranch Hand

Joined: Aug 17, 2010
Posts: 75




Help! Thanks.


OK, so that other guy knows Java better than I do, but I bet he can't speak Wuhanese(a Chinese Dialect) like me.
Komal Renu
Ranch Hand

Joined: Jul 21, 2011
Posts: 51
Hi,

I'm really not clear as to what your question is, but if you're asking that why is it that we have get(Object key) and not get(K key), is because the key in the map is an Object type which could be anything, for example String, Integer etc. whereas K is no type. Hence the method in the interface defines the type of key as Object.

Thanks and Regards,
-------------------------------------------------------------------------------------
Komal Renu | krenu@infocepts.com | www.infocepts.com
-------------------------------------------------------------------------------------
Javin Paul
Ranch Hand

Joined: Oct 15, 2010
Posts: 281


This is interesting question , get(Key K) makes a lot of sense because if you are using generics than why you want to play with object type ? let's see what experts has to say about it.

+ 1


http://javarevisited.blogspot.com - java classpath - Java67 - java hashmap - java logging tips java interview questions Java Enum Tutorial
Leon Omk
Ranch Hand

Joined: Aug 17, 2010
Posts: 75

Any other ideas?
Leon Omk
Ranch Hand

Joined: Aug 17, 2010
Posts: 75



This is the only case I can find to prove that signature get(Object o) is better than get(K key). Any other ideas?
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3615
    
  14

The reason for this is as Leon implied.

Generics are used to make life for the client of a generic class easier. It's main application is that return values don't have to be cast back to the actual type by the client, but that this behavior is automatically inserted by the compiler.

A second application is that type checks are automatically performed by the compiler as well. A List<String> contains only Strings, so the List needs to check that arguments of the add() method are indeed of type String. Generics makes sure that this is handled automatically.

So if generics are designed to make things easier, why would we restrict a client from using the Object type for methods get() and remove()? It's not like passing an Integer to a List<String>'s remove() method would break any invariants. The list doesn't contain Integers, so nothing will change after calling remove(). This is in contrast to the add() method. If it was allowed to add an Integer to a List<String>, we would break class invariants.

Leon also gave an example of how it can be useful. If you don't know what the type argument of a generic instance is, it would be impossible to call methods that require that generic type argument. Using the Object type instead allows such methods to be called.
John Schubert
Ranch Hand

Joined: Sep 21, 2011
Posts: 39

I think the only reason is to maintain backwards compatibility with the old pre-generics Map interface.

And the return tipe in V get(Object key) is compatible because of covariant return types.
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3615
    
  14

John, what about the put(K, V) method? I'm sure you don't mean to imply backwards compatibility is broken because it uses generic parameter types. And what about List's add(E) method? In fact, what about every other pre-generics class that has been retrofitted to use generics?

No, Object is a good parameter type because it makes sense, not because of backwards compatibility.
John Schubert
Ranch Hand

Joined: Sep 21, 2011
Posts: 39

@Stephan: If you read the contract for get method, it says:

More formally, if this map contains a mapping from a key k to a value v such that (key==null ? k==null : key.equals(k)), then this method returns v; otherwise it returns null. (There can be at most one such mapping.)


So it is not required for the parameter to be the same Type as the generic K, but only to be an object such as o.equals(someKeyInsideTheMap) returns true. In Java, two objects can be equal without having to be the same type.

If Mr. Josh Bloch (the JCF designer) had changed that, and the method signature were get(K key), then applications written in old pre-generics Java would not work the same. Hence the compatibility issue.
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3615
    
  14

Not at all, because of type erasure. Old programs would work fine with the new generic class if it had a generic get() method, because they use raw types.
John Schubert
Ranch Hand

Joined: Sep 21, 2011
Posts: 39

@Stephan: When I talk about compatibility, I'm not talking about bytecode compatibility, but to maintain the new contract compatible and consistent with the old one.

In the old contract, there was no need for an object to be in the key set of a Map if we passed it as parameter in the get(Object o) method. The only requirement was that if o.equals(someKey) returned true, then an object from the map is retrieved. It was decided not to change the old contract, being the main reason (in my opinion) to maintain compatibility (with the way things worked in Java 1.4).

Compatibility (in a broad sense of the word) was a big factor -if not the main one - in the generics implementation. Personally, I'd rather use get(K) or get(K extends Object), which I consider a better and more consistent design. This is also the approach taken in C#.

You can read more about this (and in a better English) in a 2007 post written by Kevin Bourrillion.
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3615
    
  14

John Schubert wrote: The only requirement was that if o.equals(someKey) returned true, then an object from the map is retrieved. It was decided not to change the old contract, being the main reason (in my opinion) to maintain compatibility (with the way things worked in Java 1.4).

Why would they have to change the contract? The contract is the same, regardless of the type of the parameter being used. The contract said nothing about what type the parameter must have. The only thing that said what type the parameter must have is the parameter itself, and the type of the parameter can be changed without breaking backwards compatibility, because of type erasure. Even the article you linked to says the backwards compatibility argument is irrelevant.

It's simply useful to have Object as the argument type, since it allows *new code* to retrieve and remove values from a map even if the code doesn't know the exact type of the keys, which is the case when it's handling a map with wildcard type arguments.

Joshua Bloch says that their first attempts at making these methods generic were awkward, and there are many reasonable programs that wouldn't work if they had.
John Schubert
Ranch Hand

Joined: Sep 21, 2011
Posts: 39

Stephan van Hulst wrote:
and the type of the parameter can be changed without breaking backwards compatibility, because of type erasure


Stephan van Hulst wrote:Joshua Bloch says that their first attempts at making these methods generic were awkward, and there are many reasonable programs that wouldn't work if they had.


Ok, so you say one thing and the contrary. Well, anyway, I have no intention to make of this post an endless discussion about compatibility. As I've said, It is just my opinion. And I think that Map<K,V> with full generics on every method is the most consistent design. Mr. Hejlsberg was also of this opinion, so the Dictionary collection in C# is fully generic, and nobody is complaining of it.

Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3615
    
  14

These things aren't contrary to each other.

Making the parameters generic (with the introduction of generics) would not break old code. Java 1.5+ code however would have difficulties. I tend to think that the Collections API would use the Object type for many methods even if Java had been designed with generics from the start.

Anyway, let's agree to disagree.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Why do we get(Object key) for interface Map<K,V>?