“Cannot create generic array of ..” - how to create an Array of Map?

前端 未结 6 2122
粉色の甜心
粉色の甜心 2020-11-28 11:39

I would like to use simpleJdbcInsert class and executeBatch method

public int[] executeBatch(Map[] batch)

http://stati

相关标签:
6条回答
  • 2020-11-28 12:11

    From Oracle tutorial [sic]:

    You cannot create arrays of parameterized types. For example, the following code does not compile:

    List<Integer>[] arrayOfLists = new List<Integer>[2];  // compile-time error
    

    The following code illustrates what happens when different types are inserted into an array:

    Object[] strings = new String[2];
    strings[0] = "hi";   // OK
    strings[1] = 100;    // An ArrayStoreException is thrown.
    

    If you try the same thing with a generic list, there would be a problem:

    Object[] stringLists = new List<String>[];  // compiler error, but pretend it's allowed
    stringLists[0] = new ArrayList<String>();   // OK
    stringLists[1] = new ArrayList<Integer>();  // An ArrayStoreException should be thrown,
                                                // but the runtime can't detect it.
    

    If arrays of parameterized lists were allowed, the previous code would fail to throw the desired ArrayStoreException.

    To me, it sounds very weak. I think that any programmer with a sufficient understanding of generics, would be perfectly fine, and even expect, that the ArrayStoredException is not thrown in such case.

    Even more, most programmers will simply do:

    List<Integer> arrayOfLists = (List<Integer>) new List[2];
    

    which will put them in exactly the same risk of ArrayStoreException not thrown.

    0 讨论(0)
  • 2020-11-28 12:18

    Because of how generics in Java work, you cannot directly create an array of a generic type (such as Map<String, Object>[]). Instead, you create an array of the raw type (Map[]) and cast it to Map<String, Object>[]. This will cause an unavoidable (but suppressible) compiler warning.

    This should work for what you need:

    Map<String, Object>[] myArray = (Map<String, Object>[]) new Map[10];
    

    You may want to annotate the method this occurs in with @SupressWarnings("unchecked"), to prevent the warning from being shown.

    0 讨论(0)
  • 2020-11-28 12:20

    As far my knowledge

    Frist try to create an array of java.lang.Object and then cast to Generic type T

    Example:

    class Example<DataType>{
        public DataType array = (DataType[]) new Object[5] ; 
    }
    

    In this way, you can create an array of generic datatype

    0 讨论(0)
  • 2020-11-28 12:30
    @SuppressWarnings("unchecked")
    private Map<String,?>[] newArray(int n) {
      return new Map[n];
    }
    

    using with a Stream of Map<String,?>:

      sql.executeBatch(myStream.toArray(this::newArray));
    

    using with a List of Map<String,?>:

      sql.executeBatch(myList.toArray(newArray(0));
    

    NOTE: the SuppressWarnings trick is actively used in JDK src - https://github.com/AdoptOpenJDK/openjdk-jdk14/blob/master/src/java.base/share/classes/java/util/ArrayList.java#L395:L404

    Credits to: @JonathanCallen

    0 讨论(0)
  • 2020-11-28 12:31

    You can create generic array of map.

    1. Create a list of maps.

      List<Map<String, ?>> myData = new ArrayList<Map<String, ?>>();
      
    2. Initialize array.

      Map<String,?>[] myDataArray = new HashMap[myData.size()];
      
    3. Populate data in array from list.

      myDataArray = myData.toArray(myDataArray);
      
    0 讨论(0)
  • 2020-11-28 12:33

    I have had some difficulty with this, but I have figured out a few things that I will share as simply as possible.

    My experience with generics is limited to collections, so I use them in the class definitions, such as:

    public class CircularArray<E> {
    

    which contains the data member:

    private E[] data;
    

    But you can't make and array of type generic, so it has the method:

    @SuppressWarnings("unchecked")
    private E[] newArray(int size)
    {
        return (E[]) new Object[size];  //Create an array of Objects then cast it as E[]
    }
    

    In the constructor:

    data = newArray(INITIAL_CAPACITY);  //Done for reusability
    

    This works for generic generics, but I needed a list that could be sorted: a list of Comparables.

    public class SortedCircularArray<E extends Comparable<E>> { 
    //any E that implements Comparable or extends a Comparable class
    

    which contains the data member:

    private E[] data;
    

    But our new class throws java.lang.ClassCastException:

    @SuppressWarnings("unchecked")
    private E[] newArray(int size)
    {
        //Old: return (E[]) new Object[size];  //Create an array of Objects then cast it as E[]
        return (E[]) new Comparable[size];  //A comparable is an object, but the converse may not be
    }
    

    In the constructor everything is the same:

    data = newArray(INITIAL_CAPACITY);  //Done for reusability
    

    I hope this helps and I hope our more experienced users will correct me if I've made mistakes.

    0 讨论(0)
提交回复
热议问题