简体   繁体   中英

Creating a new generic type array using Array.newInstance()

For practice, I'm trying to implement the merge sort algorithm but got stuck pretty fast when trying to instantiate a generic type array. I'm not entirely sure if my plan will work out, but right now the interesting part (or frustrating, depending on when you ask me) is the second row in the merge() method. The newInstance() method needs to know what class it should initiate as, but even if arr1.getClass() compiles perfectly fine, it won't work during runtime.

public void mergeSort(T[] arr) {

    T[] merged = merge(Arrays.copyOfRange(arr, 0, arr.length/2), Arrays.copyOfRange(arr, arr.length/2+1, arr.length-1));

}

@SuppressWarnings({"unchecked"})
public T[] merge(T[] arr1, T[] arr2) {
    // A new array of type T that will contain a merged version of arr1 and arr2
    T[] merged = (T[]) Array.newInstance(arr1.getClass(), arr1.length+arr2.length);

    int i1 = 0, i2 = 0;
    for (int i = 0; i < arr1.length + arr2.length; i++) {
        if (arr1[i1].compareTo(arr2[i2]) < 0) {
            merged[i] = arr1[i1];
            i1++;
        } else {
            merged[i] = arr2[i2];
            i2++;
        }
    }

    return merged;
}

The error message is:

Exception in thread "main" java.lang.ClassCastException: [[Ljava.lang.String; cannot be cast to [Ljava.lang.Comparable;
    at sort.SortingAndSearching.merge(SortingAndSearching.java:94)
    at sort.SortingAndSearching.mergeSort(SortingAndSearching.java:84)
    at sort.SortingAndSearching.main(SortingAndSearching.java:19)

Think I see the issue... When you do Array.newInstance(...) , it takes in the component type (in your case, you want it to be String). However, you're handing the array class (arr1 is of type String[], and you're doing arr1.getClass() ). Instead, do

arr1.getClass().getComponentType()

to get the String class out of String[]

Per javadoc :

 static Object newInstance(Class<?> componentType, int[] dimensions) 

componentType - the Class object representing the component type of the new array

I copied and pasted the code you gave and it doesn't even compile. After doing some fixes, I came to this:

public class Test {

  public <T extends Comparable> void mergeSort(T[] arr) {
    T[] merged = merge(Arrays.copyOfRange(arr, 0, arr.length / 2), Arrays.copyOfRange(arr, arr.length / 2 + 1, arr.length - 1));
  }

  public <T extends Comparable> T[] merge(T[] arr1, T[] arr2) {
    // A new array of type T that will contain a merged version of arr1 and arr2
    T[] merged = (T[]) Array.newInstance(arr1.getClass(), arr1.length + arr2.length);

    int i1 = 0, i2 = 0;
    for(int i = 0; i < arr1.length + arr2.length; i++) {
      if(arr1[i1].compareTo(arr2[i2]) < 0) {
        merged[i] = arr1[i1];
        i1++;
      } else {
        merged[i] = arr2[i2];
        i2++;
      }
    }
    return merged;
  }
}

Since you are using the compareTo method, you must tell the compiler that T implements this interface.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM