Java - general types and collections

I'm trying to learn about using generic types, and I noticed something strange when I was experimenting with some lines of code.

The first part of the code is inside the class named "A":

public void func(int k, List list) { list.add(9); list.add(true); list.add("a string"); } 

The second part of the code is in another class, inside the main function:

 List<Integer> arr = new ArrayList<Integer>(); arr.add(14); System.out.println(arr.toString()); a.func(8, arr); System.out.println(arr.toString()); 

Executing the code prints the following lines:

[fourteen]

[14, 9, true, string]

This puzzled me, since arr is an ArrayList type Integer , how can it contain objects of type boolean and String ? Is there a conversion of the list in the func function to a raw type (which means that it becomes a generic Object type)? And if so, how is this possible, since you cannot do this, for example: List<Integer> arr = new ArrayList<Object>(); ?

I would like to clarify this, perhaps it will help me better understand this subject of generic types. Thanks!

+5
source share
3 answers

Java does not allow the creation of shared arrays. Java Collection classes are mainly implemented using Object arrays. The ArrayList class might look like this:

 public class ArrayList<T> implements List<T>, Serializable { private transient Object[] data; // more content... } 

When you create a new ArrayList instance, a new Object[] array is created that can contain objects of any type. Security types are achieved only with a type parameter of the type.

Since List did not provide a type parameter, it uses rawtype and everything can be added to the list. Therefore, always check the template arguments to maintain security types.

 public void func(int k, List<Integer> list) { list.add(9); // works list.add(true); // compile error list.add("a string"); // compile error } 

You should never use rawtypes . Depending on your compilerโ€™s settings, warnings will be omitted. Better to use (related / unrelated) wildcards.

+1
source

The reason for this type of output is that you are passing List as a parameter to func( int k , List list ) . And the list in the func method is not universal, which allows you to add a string so that you get such output.

  List<Integer> arr = new ArrayList<Integer>(); arr.add(14); System.out.println(arr.toString()); a.func(8, arr); // here you are passing a list System.out.println(arr.toString()); public void func(List list) { // here List in non-generic list.add(9); list.add(true); list.add("a string"); } 
+1
source

The whole point of universal code in Java is to provide type security before actually compiling the code. The compiled code has no type, so we do not encounter any problem in our code, because when the func() method is actually called, List arr has no type.

When we call System.out.println(arr.toString()) , we just print the object. This will be great for any type (i.e. Int, boolean, String, etc.). That is why we are not confronted with any exception.

However, try assigning a value from this list, and we get a java.lang.ClassCastException

 ... func(8, arr); System.out.println(arr.toString()); int a = arr.get(2); 
+1
source

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


All Articles