Re: java generics bug?
On Aug 7, 12:57 pm, Muggle <zimp...@gmail.com> wrote:
On Aug 7, 11:48 am, robertjpa...@gmail.com wrote:
To sum up the problem in one sentence I would say that java does not
allow wildcards in a nested value of a Map in a method. I am using
jdk1.6.0_02 on windows.
<code>
public class Whatever{
public static void printOneDimension(Map<String,?> map){
for(String k1:map.keySet())System.out.println(k1);
}
public static void printTwoDimensions(Map<String,Map<String,?>>
map){
for(String k1:map.keySet()){
for(String k2:map.get(k1).keySet()){
System.out.println(k1+","+k2);
}
}
}
public static void main(String[] args){
Map<String,String> m1=new HashMap<String,String>();
m1.put("a",null);
m1.put("b",null);
printOneDimension(m1);
Map<String,Map<String,String>> m2=new
HashMap<String,Map<String,String>>();
m2.put("x",null);
m2.put("y",null);
printOneDimension(m2);
//printTwoDimensions(m2);}
</code>
When I run it with printTwoDimensions() comment out, I get the
following output as expected:
b
a
y
x
When I uncomment the call to printTwoDimensions(m2) gives the
compilation error:
printTwoDimensions(java.util.Map<java.lang.String,java.util.Map<java.lang.String,?>>) in StructUtils.MapUtils cannot be applied to
(java.util.Map<java.lang.String,java.util.Map<java.lang.String,java.lang.String>>)
printTwoDimensions(m2);
Java can compile printTwoDimensions fine, I just can't figure out how
to call it without a compilation error.
Although I don't think I should have to I tried casting to the
wildcard just to see what would happen:
<code>
printTwoDimensions((Map<String,Map<String,?>>)m2);
</code>
And I got this compilation error message:
inconvertible types
found :
java.util.Map<java.lang.String,java.util.Map<java.lang.String,java.lang.String>>
required:
java.util.Map<java.lang.String,java.util.Map<java.lang.String,?>>
printTwoDimensions((Map<String,Map<String,?>>)m2);
Please let me know if you think is is a bug or if I am missing
something.
Thanks,
Rob
Change the definition of m2 to
Map<String,Map<String,?>> m2=new
HashMap<String,Map<String,?>>();
Your method printTwoDimensions expects a map of Map<String,?>. A map
of Map<String,?> is not the same as a map of Map<String,String>. (In
terms of values, that is)
In the case of printOneDimension, it expects a map of (any) unknown
type. So it would work with a map of String or a map of map of String.
I changed my code as follows:
Map<String,String> m1=new HashMap<String,String>();
m1.put("a",null);
m1.put("b",null);
printOneDimension(m1);
Map<String,Map<String,?>> m2=new HashMap<String,Map<String,?
//Map<String,Map<String,String>> m2=new
HashMap<String,Map<String,String>>();
m2.put("x",m1); // Note I updated this to use m1 instead of
null
m2.put("y",m1); // since you cannot print null.
printOneDimension(m2);
printTwoDimensions(m2)
And it compiled and printed results as expected:
b
a
y
x
y,b
y,a
x,b
x,a
That said, I don't want to declare the m2 with ? as a value and I
don't understand why I should have to.
If I declare m2 with the ? as shown, I have no way to get it back to a
Map<String,Map<String,String>>. Even if casting it back worked, it
would be a pain and I don't see why it is necessary.
My understanding of wildcard '?' is that it can represent any type but
it limits your ability to perform operations that require knowing the
type. This works fine with the function printOneDimension() as the map
parameter is declared as a Map<String,?> and we never accesses the ?
(value) portion of the declaration.
By this same logic, printTwoDimensions() only accesses known parts of
the Map<String,Map<String,?>>. The compiler should be able to safely
determine that it can accept a Map<String,Map<String,Integer>> since
it never accesses the value of the nested Map.
I don't really need to solve this problem so much as I want to
understand generics better. Do you guys agree that javac "should" be
able to accept a Map<String, Map<String, ANYTHING>> as a param to
printTwoDimensions? If not why do you disagree.
Thanks, Rob.