代码之家  ›  专栏  ›  技术社区  ›  Dean J

Java中绕过类型擦除

  •  3
  • Dean J  · 技术社区  · 17 年前

    因此,与我一起工作的小组减少了我们为某些事情键入的代码量。在本例中,使用DisplayTag库显示列表的Spring网页。这样做的方式是使用泛型扩展 Controller 对象,然后为它应该处理的每个页面创建该对象的子类。

    此控制器显示 SystemErrorReport SystemErrorReportCommand .

    public class SystemErrorReportController extends
        GenericSearchAndSelectController<SystemErrorReportCommand> {
    

    问题是 SystemErrorReportCommand ,作为类型传递,需要在其构造函数中手动声明自身,如下所示:

    public SystemErrorReportCommand()
    {
        super(SystemErrorReport.class);
    }
    

    GenericCommand ,我们的另一个班级,因为 SystemErrorReportCommand 位在编译后丢失。

    我对此并不感到兴奋,因为这似乎是我们可以进一步自动化以减少开发人员错误的东西。有没有一种更优雅的方法可以做到这一点,还是因为类型擦除而让我无法摆脱?

    3 回复  |  直到 17 年前
        1
  •  4
  •   Pikalek    10 年前

    与被广泛接受和鲜为人知的情况相反,可以避免类型擦除,这意味着被调用方确实能够知道调用期间使用了哪些泛型参数。

    Using TypeTokens to retrieve generic parameters

        2
  •  3
  •   vdr    17 年前

    ((ParameterizedType) SystemErrorReportController.class.getGenericSuperType()).getActualTypeArguments[0];
    

    不过,这只是开始。您需要开始使用反射api来利用这些信息,因此,如果您不希望出现这种情况,您的设计可能会受到影响。

    以下是运行时可以提取的内容的一个小示例:

    public abstract class Test<T extends Number> extends ArrayList<Long> implements Comparable<String>, List<Long>{
        public List<String> field;
        public abstract <M> M method(List<T> arg);
    
        public static void main(String... args) throws Exception {
            TypeVariable<Class<Test>> t = Test.class.getTypeParameters()[0];
            Class<?> upperBound = (Class<?>) t.getBounds()[0];
    
    
            System.out.println("Test<" + t + " extends " + upperBound.getName() + ">");
            System.out.println("extends " + Test.class.getGenericSuperclass());
            System.out.println("implements " + Arrays.toString(Test.class.getGenericInterfaces()));
            System.out.println("{");
            System.out.println(Test.class.getMethods()[1].toGenericString());
            System.out.println(Test.class.getFields()[0].toGenericString());
            System.out.println("}");
        }
    }
    

    Test<T extends java.lang.Number>
    extends java.util.ArrayList<java.lang.Long>
    implements [java.lang.Comparable<java.lang.String>, java.util.List<java.lang.Long>]
    {
    public abstract <M> M Test.method(java.util.List<T>)
    public java.util.List<java.lang.String> Test.field
    }
    

    我正在使用 toGenericString() Field.getGenericType() , Method.getArgumentTypes , ...

        3
  •  1
  •   JRL    17 年前

    也许你可以用像 Javassist

    它被用在挂毯上,看 this