-2

I have this question regarding generics.Can anybody explain me why the options 4 and 6[i know about this option]are correct?

Consider the following code:

import java.util.*;  
public class TestClass 
{  
    public static void main(String[] args)   
    {  
    // put declaration here      
    m.put("1", new ArrayList()); //1  
    m.put(1, new Object()); //2  
    m.put(1.0, "Hello");  //3  
    System.out.println(m);  
    }  
}  

How can 'm' be declared such that the above code will compile and run without errors?

  1. Map m = new TreeMap();
  2. Map<Object, Object> m = new TreeMap<Object, Object>();
  3. Map<Object, ?> map = new LinkedHashMap<Object, Object>();
  4. Map<Object, ? super ArrayList> m = new LinkedHashMap<Object, ArrayList>();will work if lines //2 and //3 are commented out.
  5. Map<Object, ? super ArrayList> m = new LinkedHashMap<Object, ArrayList>(); will work if lines //1 and //3 are commented out.
  6. Map m = new HashMap();
Ian Roberts
  • 120,891
  • 16
  • 170
  • 183
Dahlia
  • 41
  • 11

2 Answers2

2

For understanding this problem, look at the generic signature of the Map#put method you are using here. It states:

V put(K key, V value)

what means that you can put a key that is assignable to the generic type of the Map's key type K and a value that is assignable to the generic type of the Map's value type V. This must be true for all your key-value pairs you put into the map. From your code, you are putting the following keys into the map:

  1. A String by the literal "1"
  2. An Integer by the boxed int literal 1.
  3. A Double by the boxed double literal 1.0.

The only common super type of these objects is the Object type which is required for K in order to allow all these objects to be used as a key.

For the values you have:

  1. A ArrayList instance.
  2. An Object instance
  3. A String by the literal "Hello"

Again, the only common super type of these objects is the Object type which is required for V in order to allow all these objects to be used as a map value.

As a result, only Map instances with the generic signature Map<Object, Object> are permitted. What implementation of the Map interface you choose is up to you, as long as it is assignable to the variable type of the map, i.e. you can use a LinkedHashMap, a TreeMap or a HashMap since they only differ in the way they store their data. For the generic type of the variables, note that the use of wildcards ? or ? extends ... for your variable will result in you not being able to put values into the map anymore. The tutorial I linked explains why.

As for the types with a non-generic signature you are using, they behave similar to Maps with the generic signature <Object, Object>. Such raw types should however not longer be used after the introduction of Java 5.

With all this information, you can answer your (exam) question yourself.

Community
  • 1
  • 1
Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
1

Number 4 is correct for line 1, because "1" is String which has Object superclass and ? super ArrayList means that you can use ArrayList or any superclass of ArrayList.

Number 6 is correct because you are using untyped(raw) map, so it's similar to:

Map<Object, Object> m = new HashMap<Object, Object>();

To store such values you can use Map, but it's not a really good choice. You shouldn't use untyped collections at all. Think how you can change your design to not use such map.

Jakub H
  • 2,130
  • 9
  • 16
  • "...or any superclass of ArrayList." I'm sure you meant any subclass here. – Boris Mar 05 '14 at 09:37
  • @user3301492 please read about lower bounded wildcards http://docs.oracle.com/javase/tutorial/java/generics/lowerBounded.html – Jakub H Mar 05 '14 at 09:41
  • 1
    @user3301492 It's indeed the superclass, as indicated by the **super** keyword. BTW: Although raw types are "similar" to types parameterized with ``, there are subtle differences. Simply said: In the latter case, the types are checked for consistency, whereas with raw types there is no check at all – Marco13 Mar 05 '14 at 09:41
  • Then why when using a superclass AbstractList list = new ArrayList(); m.put("1", list); is causing an Error "type Map is not applicable for the arguments (String, AbstractList)"? – Boris Mar 05 '14 at 09:45
  • @user3301492 it's because you instantiated Map as a HashMap and then you can only pass ArrayList as a value. – Jakub H Mar 05 '14 at 09:56