0

Im having a big problem with this code: I need to create my own Merge Method without using java´s Merge Method.

public static <T extends Comparable> T[] merge(T[] a, T[] b){
    T[] c = (T[]) new Object[a.length + b.length];  

    /*
     *
     * More code
     *
     *
    */
    return c;
}

The problem is that in runtime I have this error: java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable; I have already looked for this problem, and the solution is using Reflection.

The problem i have it in this line: T[ ] c = (T[ ]) new Object[a.length + b.length];

The problem is that I dont understand how to use it, have already try using reflection in many different ways but i can´t solve this.

I really appreciate any answer and tell me where should I change my code.

john
  • 1

2 Answers2

4

You could create an array of the same type as the input arrays, using reflection - something like this:

if(a.getClass() != b.getClass()) // or .equals if you prefer. It doesn't matter for Class objects
    throw new IllegalArgumentException("Arrays don't have the same type");

T[] c = Array.newInstance(a.getClass().getComponentType(), a.length + b.length);

Note that it is impossible to use something like T.class. Note also that this won't work as expected for cases like:

Comparable[] result = <Comparable>merge(new Integer[] {1, 2, 3}, new Integer[] {4, 5, 6});

as the result will be an Integer[] instead of a Comparable[]. However, it is the closest you can do without passing Comparable.class to the function, or pre-allocating the result array before calling it.

Or you could use Arrays.copyOf as suggested by Ming-Tang, and then fill the array with null (otherwise it starts with a copy of a):

if(a.getClass() != b.getClass()) // or .equals
    throw new IllegalArgumentException("Arrays don't have the same type");

T[] c = Arrays.copyOf(a, a.length + b.length);
Arrays.fill(c, null);

This has the same issues.

user253751
  • 57,427
  • 7
  • 48
  • 90
  • Because of the bizarre and unnatural behaviour of arrays, you should choose the "greatest common superclass". (Code for which is left as an exercise for the interested reader.) When I say "should", you should follow @immibis' advice and use `List`. – Tom Hawtin - tackline Mar 24 '15 at 03:03
  • @TomHawtin-tackline Note that I wrote both answers, because either one could be best for the OP's application. (Although one would certainly hope, for his/her sanity, that the List one works) – user253751 Mar 24 '15 at 03:09
  • Heh, didn't realise it was the same person. Reference arrays were badly messed up (not that `System.arraycopy` is a nice way of dealing with arrays). – Tom Hawtin - tackline Mar 24 '15 at 03:14
  • 1
    you need to cast the result of `Array.newInstance()` to `T[]` – newacct Mar 24 '15 at 19:24
2

You could just use List instead.

public static <T extends Comparable> List<T> merge(List<T> a, List<T> b){
    List<T> c = new ArrayList<T>(a.size() + b.size());

    /*
     *
     * More code
     *
     */
    return c;
}

This might not be an option if some other part of your code forces you to use arrays in merge.

user253751
  • 57,427
  • 7
  • 48
  • 90