Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using wildcard in method argument

I have declared a method whose argument is subtype of Number as given below:

public static void organizeData(java.util.List<? extends Number> c) {
    //operation on the list
}

I am able to pass any non-parameterized lists as argument. So what is the point of using wildcard <? extends Number>?

List newList = new LinkedList<>();
ClassName.organizeData(newList);

Why do I get element of type Object from c? And not of type Number? Is there a way to allow only subtypes of a type to be passed as arguments as opposed to allowing non-parameterized arguments also?

like image 667
Meena Chaudhary Avatar asked Oct 08 '14 13:10

Meena Chaudhary


1 Answers

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:

  1. 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

  1. 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.


  1. 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.

like image 169
durron597 Avatar answered Oct 12 '22 23:10

durron597