Avoiding Java Type Erasure

心不动则不痛 提交于 2019-11-27 22:17:30

问题


Is there a way one could avoid type erasure and get access to a type parameter?

public class Foo<T extends Enum<?> & Bar> {
    public Foo() {
        // access the template class here?
        // i.e. :
        baz(T.class); // obviously doesn't work
    }

    private void baz(Class<T> qux) { 
        // do stuff like
        T[] constants = qux.getEnumConstants();
        ...
    } 
}

I need to know about T, and do things with it. Is it possible, and if so, how can it be done without passing in the class in the constructor or anywhere besides the parameter?

EDIT: The main purpose of this question is to find out if there is any practical way around type erasure.


回答1:


AFACT, there is no practical way around type erasure because you can't ask for something which the runtime doesn't have access to. Assuming of course you agree that sub-classing generic classes for each enum which implements Bar interface is a practical work around.

enum Test implements Bar {
    ONE, TWO
}

class Foo<T> extends FooAbstract<Test> {
    public Foo() {
        ParameterizedType genericSuperclass =
                (ParameterizedType) getClass().getGenericSuperclass();
        baz((Class<T>) genericSuperclass.getActualTypeArguments()[0]);
    }

    private void baz(Class<T> qux) {
        T[] constants = qux.getEnumConstants();
        System.out.println(Arrays.toString(constants)); // print [ONE, TWO]
    }
}

interface Bar {
}

class FooAbstract<T extends Enum<?> & Bar> {
}



回答2:


If you're willing/able to hand a class token to the constructor:

public Foo(Class<T> clazz) {
    baz(clazz);
}

private void baz(Class<T> qux) {
    // ...
}

That way, you can produce objects of type T with Class.newInstance(), attempt to cast arbitrary objects to T using Class.cast(), etc.

What do you intend to do in baz()?




回答3:


As pholser points out in his answer, the only way to achieve this is by passing in the Class object representing the type T. It's because of Type Erasure that something like T.class isn't possible because T is erased before runtime.

You seem resistant against passing in the Class object, but it's the only way to use the method getEnumConstants(). Here is a self contained example:

public class Foo<T extends Enum<?> & Bar> {

   final Class<T> clazz;

   public Foo(Class<T> clazz) {

      this.clazz = clazz;
   }

   public void baz() {

      T[] constants = clazz.getEnumConstants();

      System.out.println(Arrays.toString(constants));
   }

   public static void main(String[] args) {

       new Foo<MyEnum>(MyEnum.class).baz(); //prints "[A, B, C, D]"
   }
}

public interface Bar { }

public enum MyEnum implements Bar { A, B, C, D; }



回答4:


Use a super type token as proposed by Neil Gafter and used by libraries like guice for this purpose.

See http://gafter.blogspot.com/2006/12/super-type-tokens.html for the original description and I've check out the guice source for CA radio life working implementation.

there is another q which has an answer with worked example inline here How can I pass a Class as parameter and return a generic collection in Java?




回答5:


In some cases you can use a workaround suggested by Richard Gomes. When creating instances of anonymous classes, the type parameter class info is available.

class A<T>
{
    A()
    {
        java.lang.reflect.ParameterizedType parameterizedType = (java.lang.reflect.ParameterizedType)  (this.getClass().getGenericSuperclass());
        System.out.println(parameterizedType.getActualTypeArguments()[0]);
    }
}

public class Example {
 public static void main(String[] args) {
     A<String> anonymous = new A<String>() {};  // prints java.lang.String
}
}

Note that multiple instances created this way will be of different anonymous classes, and if that's a problem you might want a class A_String_Factory with a createNew() function based on clone to replace the calls to new.



来源:https://stackoverflow.com/questions/8452893/avoiding-java-type-erasure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!