1

CASE 01:

public static  void processNumber(List<Number> nums){

}

If the method is invoked as below, compiler gives error.

processNumber(new ArrayList<Float>());

CASE 02 :

But on the contrary if we have below method. Here <Number> is specified as type parameter

public static <Number> void processNumber(List<Number> nums){
              ^^^^^^^^ 
}

then the below invocation not giving any error...

processNumber(new ArrayList<Float>());

Why is that so?In one case it is giving error and in another, no error..why?

Foolish
  • 3,952
  • 33
  • 46
027
  • 1,553
  • 13
  • 23
  • The signature in case 2 is equal to using `List`, where `T` is an unbounded type parameter. The `Number` type parameter is just hiding the `java.lang.Number` class. – Mick Mnemonic Jul 26 '15 at 13:43

3 Answers3

3
public static <Number> void processNumber(List<Number> nums){

}

is a generic method with an unbounded type parameter. It's the same as:

public static <T> void processNumber(List<T> nums){

}

hence when you call processNumber(new ArrayList<Float>()); the type Float is inferred by the compiler (you can also pass an ArrayList<String> for example). You just choose a bad name for the generic type parameter which maybe confused you.

On the other hand

public static  void processNumber(List<Number> nums){

}

is a method that accepts a List<Number> (the Number class) as parameter. As a List<Float> is not a subclass of List<Number>, you get a compile error.

Community
  • 1
  • 1
Alexis C.
  • 91,686
  • 21
  • 171
  • 177
  • thanks for the reply...you told that "List is not a subclass of List" I agree with that.But why the same rule is not true in case 2? Are you telling that List is not a subclass of List in case1. But List is a subclass of List in case2 and it is because of generic method. – 027 Jul 26 '15 at 13:55
  • @027 No in the case 2, you have a generic method with an unbounded type parameter, hence you can pass whatever list you want (a `List`, `List`, `List`, ...) – Alexis C. Jul 26 '15 at 14:04
  • @Alexis C, Again thanks ,But can i verify that from any way like, i can see/confirm that things(unbounded type) are replaced by Object in byte code or any other way which can give me some clue that it is generic method in case2, please give your comment if you have any idea. It would be helpful to clear my core understanding about the matter? – 027 Jul 26 '15 at 15:02
  • @027 I don't understand what you don't get exactly. But the method signature in the case 2 corresponds to how you declare a generic method (see https://docs.oracle.com/javase/tutorial/extra/generics/methods.html and the JLS https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4 with https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.4). – Alexis C. Jul 26 '15 at 15:11
1

In the 2nd Code snippet
static <Number> void processNumber(List<Number> nums){

Number is just a type variable its not the Class java.lang.Number

Hence the above code is equal to

static <T> void processNumber(List<T> nums){

Where T is type variable

Jishnu Prathap
  • 1,955
  • 2
  • 21
  • 37
0

We can see that the method parameter turns into Ljava/util/List as shown in the byte code by the compiler.See the highlighted portion in the image.

This is because we have unbounded Type Parameter in method.Hence it replaces it with Object once it is compiled.

More Detail: To implement generics, the Java compiler applies type erasure.Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded.The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.

Hence this is just the generic List as the method parameter and can accept List of any Object. not just the List of Number and its subclasses..All below invocation are correct one.

processNumber(new ArrayList<Float>());
processNumber(new ArrayList()); //raw type
processNumber(new ArrayList<String>()); //String is not subclass of Number
processNumber(new ArrayList<SampleClass1>()); //user defined class
processNumber(new ArrayList<SampleClass2>()); //user defined class

We can see that the signature turns into java/util/List as shown in the byte code by compiler, See Highlighted portion

027
  • 1,553
  • 13
  • 23