You are asking three questions here, I will answer them separately. By the way, you would find it valuable to read the Java Generics FAQ - considered by many to be the canonical reference on the subject:
- So what is the point of using wildcard
<? extends Number>
?
You need to use the wildcard for the times when the parameterized argument is a subclass of Number
, say, Integer
. For instance:
import java.util.LinkedList;
import java.util.List;
public class NumberTest {
public static void main(String... args) {
List<Integer> newList = new LinkedList<Integer>();
organizeData(newList); // This works!
anotherMethod(newList); // Doesn't compile
}
private static void organizeData(List<? extends Number> list) {
}
private static void anotherMethod(List<Number> list) {
}
}
The second method call fails with the compilation error:
NumberTest.java:9: error: method anotherMethod in class NumberTest cannot be applied to given types;
anotherMethod(newList); // Doesn't compile
^
required: List<Number>
found: List<Integer>
reason: actual argument List<Integer> cannot be converted to List<Number> by method invocation conversion
1 error
- Why do I get element of type
Object
from c
? And not of type Number
?
The reason you get a type of Object
in your second case is because you are using the Raw Type. You should never use a raw type if you can avoid it for that reason - you lose all the advantages of compiler type checking.
- Is there a way to allow only subtypes of a type to be passed as arguments as opposed to allowing non-parameterized arguments also?
You cannot prevent Heap Pollution in the way you describe because someone can always cast to the Raw type and then to whatever is required. Generics are a compile time only construct, and are ultimately erased after compilation. This is why the Unchecked Type Conversion warning can only be suppressed via annotation.