2

I am working on a code, containing the following lines:

 public static int[] toArray(List<Integer> list) {
   int[] array = new int[list.size()];
   for(int i = 0; i < array.length; i++)
     array[i] = list.get(i);
   return array;
 }
 public static double[] toArray(List<Double> list) {
   double[] array = new double[list.size()];
   for(int i = 0; i < array.length; i++)
     array[i] = list.get(i);
   return array;
 }
 public static String[] toArray(List<String> list) {
   String[] data = new String[list.size()];
   for(int i = 0; i < data.length; i++)
     data[i] = list.get(i);
   return data;

while compiling I get the following errors:

error: name clash: toArray(List<Double>) and toArray(List<Integer>) have the same erasure
 public static double[] toArray(List<Double> list) {
                        ^
error: name clash: toArray(List<String>) and toArray(List<Integer>) have the same erasure
 public static String[] toArray(List<String> list) {
                        ^
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
2 errors

This program is an open source program (and a bit old, 2006) that I recently downloaded. In the package I could find both binary version and the source code. It means that this code has been compiled correctly, but now I can not compile it.

Now I have 2 questions:

  1. What is wrong with this overloadings?
  2. How I can resolve this problem? May I replace these functions with just a function that is based on templates? If so, how?

Thanks

amin
  • 445
  • 1
  • 4
  • 14

4 Answers4

3

Make the method generic:

 public static T[] toArray(List<T> list) {
   T[] data = new T[list.size()];
   for(int i = 0; i < data.length; i++)
     data[i] = list.get(i);
   return data;

Might not be syntactically correct, a while since ive written java :) The solution should hold though

Logard
  • 1,494
  • 1
  • 13
  • 27
  • 1
    The problem is that `T` cannot stand for a primitive type; that will give a list of `Integer`, `Double` etc. – fge Jun 28 '13 at 07:30
  • 1
    All primitive types in java has wrapper types that can be used with generics. int has Integer, double has Double etc. You can use these to achieve what you want. Making one generic method makes more sense than writing three or more methods that do the same only from different types – Logard Jun 28 '13 at 07:31
  • 1
    read what I say again; you cannot obtain an array of `int[]` from a generic method! – fge Jun 28 '13 at 07:33
  • Do you specifically need to have the basetype array returned? – Logard Jun 28 '13 at 07:35
  • 2
    Look at what the OP wants from the code it has. Seems quite obvious to me – fge Jun 28 '13 at 07:35
  • 1
    How is it obvious? By the returns in the methods? If he specifically neeed int[] instead of Integer[], allthough i cant understand why, I would suggest to make a utility method using reflection to get the basetype and then converting from the wrapper type – Logard Jun 28 '13 at 07:39
  • 2
    Well, yes, from the return of the methods, as you say. Also, why recreate the wheel when `List` has the method already? – fge Jun 28 '13 at 07:44
  • It is like solving a different problem. OP's method is `public static int[] toArray` instead of `public static Integer[] toArray` – anubhava Jun 28 '13 at 07:46
3

The name clashes happen because of type erasure.

On the other hand, you probably don't need those methods at all, as you can use the List.toArray method directly.

For instance:

List<Double> myList = new ArrayList<Double>();
Double[] myArray = myList.toArray(new Double[]{});
Mena
  • 47,782
  • 11
  • 87
  • 106
  • 1
    Read the question again. OP wants a `double[]` not `Double[]` – anubhava Jun 28 '13 at 07:35
  • 2
    @anubhava not sure this is a requirement. If that were true, I would just point to [this](http://stackoverflow.com/questions/960431/how-to-convert-listinteger-to-int-in-java) existing thread. – Mena Jun 28 '13 at 07:39
  • Check the question again. `public static int[] toArray` instead of `public static Integer[] toArray` – anubhava Jun 28 '13 at 07:44
2

Looks like your code was written for Java 4 or less originally.

Don't bother yourself, List already has such a method, just use that.

For String, at least. For primitive types, you can't do that (a type parameter cannot stand for a primitive type). You have to write methods yourself, with different names, since at run time, List<X> becomes List for whatever X. This is called type erasure.

This means that all of your toArray methods really have a prototype of toArray(List). So, create toIntArray(), toDoubleArray(), etc...

Or just use Guava which has:

Otherwise, coding that yourself is easy:

int[] toIntArray(final Collection<? extends Number> c)
{
    final int[] ret = new int[c.size()];
    int i = 0;
    for (final Number n: c)
        ret[i++] = n.intValue();
    return ret;
}

Do the same for double etc.

fge
  • 119,121
  • 33
  • 254
  • 329
0

If you want to convert a primitive array from corresponding List of its wrapper type then you can use Apache common's ArrayUtils#toPrimitive

For ex:

int[] intArray = ArrayUtils.toPrimitive(list.toArray(new Integer[list.size()]));
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • Thanks guys. But this seems that I have more problems with this code.due the age of the code. after fixing these stuff I faced some others. so, I prefer to leave it. – amin Jun 28 '13 at 08:54