Tim Bant wrote:I feel like I understand generics and its purpose, particularly around upper and lower bounding, I get that.
However, I can't quite work out what unbounded wildcards ? are really doing... Is it simply, being translated by the compiler as Object?
No, better to say it's being translated as a List with lower bound of Object, a List<? extends Object>. But it's still a wildcard.
Tim Bant wrote:Thus, why doesn't the below compile? I can't see the purpose of the unbounded wildcard (?).
Well to answer the easier part first, there is no purpose; it doesn't make any sense here.
But the reason it doesn't compile is, since aList is a List<?>, the compiler treats it as if it might be a List of anything - a List<Object> or List<String> or List<Integer> or List<SomeUnknownClass>. So when you get to
that could make sense if it were a List<Object> or List<String>. But not if it's a List<Integer> or List<SomeUnknownClass>. Because the string "Hello" is not a subtype of Integer or SomeUnknownClass. So, the compiler can't allow that, and doesn't.
There is, of course, no reason to declare the type as List<?> if you
know you're going to want to add a String to it later. You can't do that. You might want to declare a List<?> for other reasons - Jhonson gave a good example of that. But in that example, he didn't try to add anything to the list, in the code that declared it as List<?>. Rather, the list was created outside that method, and passed in. He didn't need to add anything, or use any method calls on the elements of the list, other than an implicit call to toString() which is guaranteed to exist for any object.