Re: Java type-casting -- Q1
On 09/25/2009 06:02 PM, grz01 wrote:
I discovered, however, that this works:
List<String> sList = new ArrayList<String>();
List<?> oList = sList;
What's the significant difference between the two?
The best way to approach a generics error or warning is often to think
about "how would allowing this action cause type safety to break?"
In your first example, you tried treating a List<String> as a
List<Object>, which is likely a natural inclination, since a String is a
Object. But it really isn't right:
List<String> sl = new ArrayList<String>();
List<Object> ol = sl; // Let's pretend this worked
ol.add(new Integer(5)); // Integers are also Objects...
sl.get(0); // but they're not Strings!
You should now see why allowing the simple cast is not so good of an
idea. If you're smart, you'll retort that you can do the cast with
arrays. But it's not quite the same thing:
String[] sa = new String[1];
Object[] oa = sa; // This works, of course
oa[0] = new Integer(5); // The compiler doesn't complain here.
String s = sa[0];
The compiler doesn't complain, but the runtime sure does. When you try
storing the integer, you get an ArrayStoreException. Compare this to the
generics case, where you get a ClassCastException at the point of retrieval.
The solution that Java come up with was wildcard generics. How these
exactly work is outside the scope of the post, but the type system rules
and method resolution rules are set up to avoid the possibility that I
described here:
List<String> sl = new ArrayList<String>();
List<? extends Object> wol = sl; // Same as List<?>, but being explicit
wol.add(new Integer(5)); // Compiler says "no such method" [1]
Object o = wol.get(0); // No problems here
[1] Unfortunately, javac seems to love to give the same error message in
response to errant misspellings as errant type conversions.
--
Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth