Home > Back-end >  Java generic List name clash, has same erasure
Java generic List name clash, has same erasure

Time:11-02

I am writing a method with a generic List<T> as an argument. I want to limit T to Integer, Float and Double with this:

private Method(List<T> list) {
    this.list = list;
}

public static <T extends Integer> Method<T> create(List<T> list) {
    return new Method<>(list);
}

public static <T extends Float> Method<T> create(List<T> list) {
    return new Method<>(list);
}

public static <T extends Double> Method<T> create(List<T> list) {
    return new Method<>(list);
}

But I get this error:

error: name clash: <T#1>create(List<T#1>) and <T#2>create(List<T#2>) have the same erasure                                                                                                                                 
        public static <T extends Float> Method<T> create(List<T> list) {                                                             
                                                      ^                                                                                    
  where T#1,T#2 are type-variables:                                                                                                        
    T#1 extends Float declared in method <T#1>create(List<T#1>)                                                                            
    T#2 extends Integer declared in method <T#2>create(List<T#2>)

I get the same error for T#1 extends Double as well.

The code is based on this answer, which works well. So I think the problem is related to the fact that I used a list of generics as an input instead of a single generic.

How can I fix this? Is there some way to give Java the ability to discern between the different instances?

CodePudding user response:

You could use the Number superclass of Integer, Float, and Double as your bound.

public class Method<T extends Number> {
  private final List<T> list;

  public Method(List<T> list) {
    this.list = list;
  }

  public static void main(String[] args) {
    var mFloats = new Method(Arrays.asList(1.0f, 2.0f, 3.0f));
    var mDoubles =  new Method(Arrays.asList(1.0,2.0,3.0));
    var mInts = new Method(Arrays.asList(1,2,3));
  }
}

CodePudding user response:

Type Erasure affects Generic Collections like List, so each generic method is type erased into having a parameter signature with parameter type Obejct. See Oracle Docs To avoid this you can use arrays instead.

import java.util.Arrays;
import java.util.List;

public class Method<T> {
  private final List<T> list;
  private Method(List<T> list) {
    this.list = list;
  }

  public static <T extends Integer> Method<T> create(T[] arr) {
    return new Method<>(Arrays.asList(arr));
  }

  public static <T extends Float> Method<T> create(T[] arr) {
    return new Method<>(Arrays.asList(arr));
  }

  public static <T extends Double> Method<T> create(T[] arr) {
    return new Method<>(Arrays.asList(arr));
  }

  public static void main(String[] args) {
    var floatMethod = Method.create(new Float[] {1.0f, 2.0f});
    var doubleMethod = Method.create(new Double[] {1.0, 2.0});
    var intMethod = Method.create(new Integer[] {1, 2});
  }
}
  • Related