将List <object []>转换为List <integer>时出现歧义

时间:2018-03-06 07:08:09

标签: java list data-conversion

我们尝试使用SQL通过hibernate查询从数据库中获取结果,如果存在记录,则List<Object[]>将返回List<Integer>。但后来我们想把它转换成Object[]。因此,我们没有迭代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); } } 列表并继续添加到整数列表,而是尝试了一些东西,示例代码就像

Arrays

我们只是尝试从查询中获取一列,这就是为什么所有intList只有一个元素。 Case-1 Case-2 分别执行,两种情况下输出相同,就像这样

  

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

案例1 List<Integer> List类型指向Object[]的{​​{1}}对象。我们期望在运行时出现异常,因为数据类型完全不同。

案例2 中,我们明确地将Object[]添加到List<Integer>,并且没有任何例外,它会提供据我所知的输出。

  1. 那么有人可以解释为什么我们这样得到输出吗?
  2. List<Integer>在其所有位置仅预计Integers,如何保存此[[Ljava.lang.Object;@3e25a5, [Ljava.lang.Object;@19821f]这样的数据?
  3. 为什么Java允许用户将原始数据列表中的数据添加到通用列表中。在我的代码中,如果我生成Object[] ob1 = {1, 2, "3", "abc"};,则可以将intList添加到intList.addAll(objList);,这是#pragma pack(push,1) struct xyzzy { BITMAPINFOHEADER header; char plugh; long twisty; } myVar; 允许并且可以顺利运行。

3 个答案:

答案 0 :(得分:10)

@Arun Sudhakaran,你提出的三个问题可以这样回答:

问题1:

案例1:

你说: intList一种List<Integer>,指的是List的{​​{1}}对象

这是不正确的,因为您没有使用参数Object[]初始化objList;您正在初始化<Object[]>,如下所示:列出objList = new ArrayList();

通过这样做,objList将创建为objList 原始类型,而不是List类型List

(更多关于原始类型: https://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html

由于Object[]是一种intList,这意味着List<Integer>指向intList的对象,其中原始类型 - 不是List类型为List的对象。

JDK 1.5 以来,泛型一直是Java的一部分。为了保持向后兼容性,Java尚未使用 raw-type 删除集合初始化。

Object[]

在这种情况下,使用原始类型初始化//Case - 1 List<Integer> intList = objList; 。通过将objList指向intList,编译器不知道objList集合变量所持有的值的类型。这就是编译器允许您将objList数组添加到Object

的原因

案例2:

objList

您说:我们明确将//Case - 2 List<Integer> intList = new ArrayList<Integer>(); intList.addAll(objList); System.out.println(intList); 添加到Object[],毫无例外地它提供输出

再次,这是不正确的。您要将List<Integer>类型List添加到Object[] - 而非List<Integer>添加到Object[]。你没有List<Integer>。如果您这样做,那么您可以说我们正在intList.add(ob1); intList.add(ob2);添加Object[]

JDK 1.5 开始,您可以使用泛型初始化集合变量,如下所示:

List<Integer>

之后,当尝试将元素添加到List<Integer> list = new ArrayList<>(); //or List<?> list = new ArrayList<>(); 时,编译器将检查该元素是否具有与list相同的数据类型或相同的list子类型。当您将鼠标悬停在eclipse或intelliJ等IDE中的集合变量上时,您可能会看到类似list的内容。

但是在这里,List<? extends Integer>初始化为原始类型而不是泛型类型。这意味着编译器不知道objList不是objList类型或子类型Integer。如果是这种情况,编译器不会抛出异常。相反,编译器将遍历列表并提供Integerob1和`ob3的参考值。

问题2:

在编译时尝试将ob2的所有元素添加到objList时,编译器将不知道List<Integer>的数据类型,因为objList是<强>生型即可。因此,编译器不会抛出异常。相反,编译器将允许用户将此类元素添加到objList中。在尝试迭代List<Integer>时,您会在List<Integer>中找到objListob1ob2中元素的参考值。

问题3:

Java仅允许用户将原始数据列表中的数据添加到通用列表中。这样做是为了支持兼容性,这是您的代码在 JDK 1.4 JDK 1.8 中顺利运行而不更改任何代码的原因。< / p>

答案 1 :(得分:3)

在休眠状态下,数组中的每个Object代表一个选定的实体(表)。

最好是将查询限制在所需的结果中:

const getId = obj.id ? obj.id : obj.id2

假设您还需要扩展数据用于其他目的:

  String hql = "select count(me.grp) from  MyEntity me group by grp";
  TypedQuery<Integer> query = entityManager.createQuery(hql, Integer.class);
  List<Integer> result = query.getResult();

对于没有int的hibernate查询 List<Integer> result = objList.stream() .map(oarr -> oarr[0]) .map(Integer.class::cast) .collect(Collectors.toList()); ,但是A类:

select A a, B b, C c

代码

如果输入objList,则无法编译。

List<Object[]> objList = ...

List<Integer> result = objList.stream()
          .map(oarr -> oarr[0])           // Object[] to Object
          .map(A.class::cast)             // Object to A
          .map(A::getId)                  // A to int A.getId()
          .collect(Collectors.toList());

没有类型参数,整个通用类型不会占用 List<Object[]> objList = new ArrayList<>(); ,因此即使对于objList也是如此。使用类型擦除intList只是一个对象列表,一切正常。

答案 2 :(得分:1)

我不确定这是不是答案,但我没有足够的声誉来评论,所以我把它放在这里。

Look at the method signature for addAll()

public boolean addAll(Collection<? extends E> c)

参数是上限通配符。由于以下行,代码中的objList是原始类型:

List objList = new ArrayList();

这使addAll()将所有类型的ArrayLists作为参数。将您的代码更改为此,您将收到您所期望的错误:

List<Integer> objList = new ArrayList<>();