3

Why can't I make two overloaded methods whose parameters are both array lists, but with different data types?

public class test {
  public static void main(String[] args){

    ArrayList<Integer> ints = new ArrayList<Integer>();
    ints.add(1);
    ints.add(2);
    ints.add(3);
    ints.add(4);
    ints.add(5);

    showFirst(ints);

    ArrayList<Double> dubs = new ArrayList<Double>();
    dubs.add(1.1);
    dubs.add(2.2);
    dubs.add(3.3);
    dubs.add(4.4);
    dubs.add(5.5);

    showFirst(dubs);
  } 

  public static void showFirst(ArrayList<Integer> a)
  {
    System.out.println(a.remove(0));
  }

  public static void showFirst(ArrayList<Double> a)
  {
    System.out.println(a.remove(0));
  }
}

I am in eclipse, and it underlines the problem causing code in red and gives this message: Method showFirst(ArrayList<Integer>) has the same erasure showFirst(ArrayList<E>) as another method in type test

The only way I could get it to work is my adding other parameters, such as , int b after showFirst(ArrayList<Integer> a and , int b after showFirst(ArrayList<Double> a.

Is there any way to make this code work the way I intended? If not, I'd like to know why this is happening.

Running the program generates the following error message:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
  The method showFirst(ArrayList<Integer>) in the type test is not applicable for the arguments (ArrayList<Double>)
at test.test.main(test.java:25)

Edit:

Using or , what if I wanted to do things where I need the data type such as:

public static int[] reverseInArray(ArrayList<Integer> a)
  {
    int n = a.size();
    int[] b = new int[n];
    while(n > 0)
    {
    b[n] = a.remove(0);
    n--;
    }
    return b;
  }

  public static double[] reverseInArray(ArrayList<Double> a)
  {
    double n = a.size();
    double[] b = new int[n];
    while(I > 0)
    {
    b[n] = a.remove(0);
    n--;
    }
    return b;
  }
1
  • Look into type erasure. Commented Mar 5, 2014 at 16:45

5 Answers 5

12

At run time, every ArrayList<Whatever> will be converted to ArrayList (raw) due to type erasure. So, just have one method that receives List<? extends Number>.

//renamed to show what the method really does
public static void removeFirst(List<? extends Number> a) {
    System.out.println(a.remove(0));
}

Note that the method above will work only for Lists (ArrayList, LinkedList and other implementations of List) which declares to hold a class that extends from Number. If you want/need a method to remove the first element from List that holds any type, use List<?> instead:

public static void removeFirst(List<?> a) {
    System.out.println(a.remove(0));
}

Remember to always program to interfaces instead of specific class implementation.

Sign up to request clarification or add additional context in comments.

3 Comments

+1 In fact, List<?> would be the most appropriate.
@PaulBellora answer updated reflecting the difference between List<? extends Number> and List<?>.
+1 as an advice.. method's name should be the most declarative as possible ..if you call a method showFirst i expect that that method don't remove an element from the list!
3

Generics are only enforced at compile time. At runtime an ArrayList is an ArrayList.

You can combine the two methods in this particular case, though:

public static void showFirst(ArrayList<? extends Number> a)
{
    System.out.println(a.remove(0));
}

Comments

3

Because generics are erased at runtime. In other words, your code doesn't know that the two methods are different. In fact, you have another compiler error that you're not telling us about:

Method showFirst(ArrayList<Integer>) has the same erasure showFirst(ArrayList<E>) as another method in type Main

Comments

3

... because of type erasure, your generic parameters are unknown at runtime, hence your overridden methods share an ambiguous signature.

Comments

2

Have this method only, because, generics are available only in compile, so, both of your methods are compiled to same signature. So it's ambiguous which method to be called

public static void showFirst(ArrayList<? extends Number> a)
{
    System.out.println(a.remove(0));
}

3 Comments

This doesn't answer the question.
-1 generics are available only in runtime, not true at all.. at compile-time ;)
@Nachokk : Corrected, It was a typo.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.