3

I have two types of lists:

ArrayList<String> sList;
ArrayList<Resource rList;

I can call a .getName() method on the resource object.

I want to be able to print out either of those lists by calling a printList(list) metod like this:

printList(sList);
printList(rList);

And the code for them would look like this:

private static void printList(ArrayList<String> list){
    for(String s : list){
        System.out.println(s + ", ");
   }
}

private static void printList(ArrayList<Resource> list){
    for(Resource r : list){
        System.out.println(r.getName() + ", ");
   }
}

I don't have any particular reason for using private static, it just happened to be like that because eclipse suggested it.

The code, however, does not work. Eclipse gives me following error:

"Method printList(ArrayList) has the same erasure printList(ArrayList) as another method in type GUI"

GUI is my class. What is wrong?

EDIT: Is there any alternative or work-around to get the functionality I want?

Goatcat
  • 1,133
  • 2
  • 14
  • 31

4 Answers4

6

Due to type erasure both methods have the same signature, i.e. the compiler sees them both

as

private static void printList(ArrayList list)

making then indistinguishable from each other and causing the compilation error. You need to change the signature if you wish the code to compile, e.g.

private static void printStringList(ArrayList<String> list)
private static void printResourceList(ArrayList<Resource> list)

or if toString has been overridden in all List types, you can use polymorphism to your advantage by using generic format such as

private static <T> void printList(List<T> list) {
    for (T t: list) {
        System.out.println(t);
    }
}
Reimeus
  • 158,255
  • 15
  • 216
  • 276
  • Is it possible to do something like: `private static void printList(ArrayList list){ if(list.getClass().equals(ArrayList)){ //do something }else if(list.getClass().equals(ArrayList)){ //do something else }else{ //do something else } }` – Goatcat Jun 20 '13 at 14:54
  • Sorry, didn't have time to edit it so it looks good, hope you can understand anyway! – Goatcat Jun 20 '13 at 15:01
  • 1
    You can't use that format as you run into the type erasure problem again. However if the result of `toString` for `Resource` is intelligible then you can use the format shown in the update. This would be preferable to keep things simple for that approach – Reimeus Jun 20 '13 at 16:00
2

During the type erasure process, the Java compiler erases all type parameters and replaces each with its first bound if the type parameter is bounded, or Object if the type parameter is unbounded.

After the Erasure of Generic Types JVM treats them as

private static void printList(ArrayList<> list){
    for(String s : list){
        System.out.println(s + ", ");
   }
}

private static void printList(ArrayList<> list){
    for(Resource r : list){
        System.out.println(r.getName() + ", ");
   }
}
Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
2

Your two printList methods have the same method signatures. Using a different generic type does not make the arguments different for overloading purposes. The compiler just sees

private static void printList(ArrayList list)
private static void printList(ArrayList list)

So it can't figure out which method you want to call.

If you want to have two separate printList methods, they need to have different signatures.

Note the static is just because the methods don't access any instance variables.

Jeff Storey
  • 56,312
  • 72
  • 233
  • 406
1

the generics Resource/String is only existent at compiler time. At runtime it is not possible to distinguish the two methods

Manuel Manhart
  • 4,819
  • 3
  • 24
  • 28