Using a template in a method argument

I have declared a method whose argument is a subtype of Number , as follows:

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

I can pass any non-parameterized lists as an argument. So, what's the point of using a wildcard <? extends Number> <? extends Number> ?

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

Why am I getting an element of type Object from c ? And not of type Number ? Is there a way to allow passing only subtypes of type as arguments, and not allow non-parameterized arguments as well?

+5
source share
3 answers

Here you ask three questions, I will answer them separately. By the way, it would be useful for you to read the Java Generics Frequently Asked Questions - many of which were canonical links to the topic :

  • So what is the point of using the wildcard character <? extends Number> <? extends Number> ?

You need to use a wildcard for the time 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 a 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 am I getting an element of type Object from c ? And not of type Number ?

The reason you get the Object type in the second case is because you are using the Raw Type. You should never use a raw type, if you can avoid it for this reason - you lose all the benefits of compiler type checking.


  1. Is there a way to allow passing only subtypes of type as arguments, and not allow non-parameterized arguments?

You cannot interfere with Heap Pollution in the way you describe, because someone can always be classified as Raw, and then what is required. Generics is a compilation of time, only a design, and ultimately erased after compilation. That is why the Unchecked Type Conversion warning can only be suppressed through annotation.

+6
source

You must remember that in Java generics, it is a compile-time construction that helps with type safety. At run time, type erasing converts all common types to Object and adds casting if necessary. If you bypass compile-time checking using raw types (for which the compiler gives you a warning), you have bypassed the benefits of generics (compile-time type checking and safe casting).

+1
source

Generators in Java are implemented using type erasure. ie: enter the information specified in <> does not exist at run time. During compilation, the java compiler uses the information specified in <> to ensure that everything is in order. If, however, you do not specify the type in <> as you did for the variable 'newList', nothing prevents you from passing it to the organizData method.

0
source

Source: https://habr.com/ru/post/1204260/


All Articles