Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguities while converting List<Object[]> to List<Integer>

We were trying to fetch results from database via SQL query using hibernate which will return List<Object[]>, if records are present. But later we want to convert it into a List<Integer>. So instead of iterating through the Object[] list and keep on adding to integer list, we tried something and the sample code is like

public class ListObjectArrayToListInteger {
    public static void main(String[] args) {
        Object[] ob1 = {1};
        Object[] ob2 = {5};
        Object[] ob3 = {9};
        List objList = new ArrayList();
        objList.add(ob1);
        objList.add(ob2);
        objList.add(ob3);

        //Case - 1
        List<Integer> intList = objList;
        System.out.println(intList);

        //Case - 2          
        List<Integer> intList = new ArrayList<Integer>();
        intList.addAll(objList);
        System.out.println(intList);
    }
}

We are only trying to fetch one column from the query and that's why all the Arrays are having only one element. Both Case-1 and Case-2 were executed separately and output was same in both case, it was something like this

[[Ljava.lang.Object;@3e25a5, [Ljava.lang.Object;@19821f, [Ljava.lang.Object;@addbf1]

In Case-1 intList a type of List<Integer>, is pointing to an object of List with Object[]s. We were expecting an Exception in run time because the data types are entirely different.

In Case-2 we are explicitly adding Object[]s to List<Integer> and without any exception it is giving an output which up to my knowledge is wiered.

  1. So can anybody explain why we are getting output like this?
  2. How a List<Integer>, which is expecting only Integers at all its locations, would hold a data like this [[Ljava.lang.Object;@3e25a5, [Ljava.lang.Object;@19821f]?
  3. Why would Java allow users to add data from a raw data list to a generic list. In my code if I make Object[] ob1 = {1, 2, "3", "abc"}; it can be added to intList as intList.addAll(objList); which is allowed and runs smoothly.
like image 875
Arun Sudhakaran Avatar asked Dec 11 '22 07:12

Arun Sudhakaran


1 Answers

@Arun Sudhakaran, The three questions you asked can be answered like this:

Question 1:

Case 1:

You said: "intList a type of List<Integer>, is pointing to an object of List with Object[]s ".

This is incorrect because you are not initializing objList with the parameter <Object[]>; you are initializing objList like this: List objList = new ArrayList();.

By doing so, objList will be created as a List with raw-type, not as a List with type Object[].

(more on raw-type: https://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html)

Since intList is a type of List<Integer>, this means that intList is pointing to an object of List with raw-type- not to an object of List with type Object[]s.

Generics have been a part of Java since JDK 1.5. To maintain backward compatibility, Java has not removed collection initialization with raw-type.

//Case - 1
List<Integer> intList = objList;

In this case, objList is initialized with raw-type. By pointing intList to objList, the compiler does not know the type of value the objList collection variable is holding. This is why the compiler allows you to add an array of Object into objList.

Case 2:

//Case - 2          
List<Integer> intList = new ArrayList<Integer>();
intList.addAll(objList);
System.out.println(intList);

You said: " we are explicitly adding Object[]s to List<Integer> and without any exception it is giving an output "

Again, This is incorrect. You are adding a List of type Object[] into List<Integer>- not Object[]s into List<Integer>. You are not doing intList.add(ob1); intList.add(ob2);. If you did this, then you could say that we are adding Object[]s into List<Integer>.

From JDK 1.5 and onward, you can use generics to initialize collection variables like this:

List<Integer> list = new ArrayList<>(); //or
List<?> list = new ArrayList<>();

After that, when trying to add elements into list, the compiler will check whether or not the element has the same datatype as list or same sub-type of list. When you hover over a collection variable in IDEs like eclipse or intelliJ, you may see something like List<? extends Integer>.

But here, objList is initialized with raw-type not a generic type. This means the compiler does not know that objList is not of type Integer or of sub-type Integer. If this is the case, the compiler will not throw an exception. Instead, the compiler will traverse the list and give the reference values of ob1, ob2 and `ob3.

Question 2:

When trying to add all elements of objList into List<Integer>, at compile time, the compiler will not know the data-type of objList because objList is of raw-type. As a result, the compiler will not throw an exception. Instead, the compiler will allow the user to add such element into List<Integer>. When trying to iterate through List<Integer>, you will find the reference value of the elements in objList which are ob1, ob2 and ob3.

Question 3:

Java only allows users to add data from a raw data list to the generic list. This is done to support compatibility and is the reason that your code will run smoothly in both JDK 1.4 and JDK 1.8 without changing any code.

like image 138
Harsh Mehta Avatar answered Dec 30 '22 14:12

Harsh Mehta