Java 将类实例用作泛型类型

Java 将类实例用作泛型类型,java,class,enums,Java,Class,Enums,有没有办法使用SomeClass.class作为类型的泛型类型 例如,我有一个枚举: enum MyEnum { FOO(String.class); private Class fooClass; private MyEnum(Class fooClass) { this.fooClass = fooClass; } public Class getFooClass(){ return fooClass; } }

有没有办法使用
SomeClass.class
作为类型的泛型类型

例如,我有一个枚举:

enum MyEnum {
    FOO(String.class);
    private Class fooClass;
    private MyEnum(Class fooClass) {
        this.fooClass = fooClass;
    }
    public Class getFooClass(){
        return fooClass;
    }
}
然后在我的代码中的某个地方:

List<MyEnum.FOO.getFooClass()> list = new ArrayList<>();
List List=new ArrayList();

泛型类型是在编译时使用的,而不是在运行时使用的-看看Java是如何将擦除与泛型一起使用的。因此,你不能这样做

您可以做的是,在遍历列表时对枚举中的类使用方法,但即使这样,您也无法执行任何动态泛型赋值。

否。 泛型在编译时求值,而此调用的值:

MyEnum.FOO.getFooClass()

只有在运行时才知道

这是不可能的,因为一个显而易见的事实:
FOO.getFooClass()
表达式的值是
runtime
计算的,而所有泛型都是
编译时处理的,并且在
运行时
中没有关于泛型类型的任何信息。

正如其他人已经说过的,您不能。 请查看此处以了解更多信息:

事实上,这一可能需要一些技巧,这就是为什么GSON能够从JSON构建
List
——它使用
TypeToken
类来解析匿名TypeToken实现的“类型化泛型超类”

基于这一点,我认为如果我们能够以某种方式提取JSON反序列化,并像这样构造列表本身,那么应该可以从
对象中获取
列表
实例

然后我尝试了这个:

public static abstract class MyTypeToken<T> {
    public T factory() {
        try {
            Type type = getClass().getGenericSuperclass();
            ParameterizedType paramType = (ParameterizedType) type;
            return ((Class<T>) paramType.getActualTypeArguments()[0]).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}
所以我很确定Google遇到了这种情况,正如他们在中的魔法代码所表明的,更重要的是,他们使用内部Sun类的重新实现版本,比如
ParameterizedTypeImpl
等等(因为他们有私人访问权)

因此,如果您创建这样的“枚举”:

public static abstract class MyEnum<T> {
    public static final MyEnum<String> FOO = new MyEnum<String>(new MyTypeToken<String>() {}) {};

    protected MyTypeToken<T> typeToken;

    private MyEnum(MyTypeToken<T> typeToken) {
        this.typeToken = typeToken;
    }

    public MyTypeToken<T> getTypeToken() {
        return typeToken;
    }
}

public void execute() {
    String string = MyEnum.FOO.getTypeToken().factory();
    System.out.println(string.getClass().getName());
}

所以我猜如果你不想窃取GSON内部代码,你能做的就是(使用GSON及其自己的TypeToken):

输出是

hello
但是是的,你不能做像这样的事情

List<MyEnum.FOO.getFooClass()> 
列表

你需要知道你得到的对象是一个
列表

你能再显示几行代码来明确你将如何使用这个
列表
?泛型用于启用编译类型检查。如果在编译时不知道组件类型,那么这里就没有什么可以做的了。我不确定您将如何处理
.class
类型列表。如果我没有错的话,对于一个给定的类加载器(不管您创建了多少个类对象),在运行时只有一个
class
对象对应于一个
class
。@ChetanKinger:这不是类类型的列表。它是基于枚举的
列表
列表
或任何内容。(我不确定这与仅仅
List
List
)相比的目的是什么。)那么Java首先允许以这种方式创建列表吗?是否允许
列表
List
在语法上是否可能?Re:
cast
。对。我把它和集合混淆了。checkedList(list,String.class)
(它根据假定的编译时类型进行运行时检查)。匿名子类包含关于其父类的
类型
信息。当然,您不能从
foo.getClass()获取它。没必要粗鲁。
public <T> List<T> getList(Class<T> clazz) {
    MyTypeToken<ArrayList<T>> token = new MyTypeToken<ArrayList<T>>() {};
    return token.factory();
}
Exception in thread "main" java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl cannot be cast to java.lang.Class
public static abstract class MyEnum<T> {
    public static final MyEnum<String> FOO = new MyEnum<String>(new MyTypeToken<String>() {}) {};

    protected MyTypeToken<T> typeToken;

    private MyEnum(MyTypeToken<T> typeToken) {
        this.typeToken = typeToken;
    }

    public MyTypeToken<T> getTypeToken() {
        return typeToken;
    }
}

public void execute() {
    String string = MyEnum.FOO.getTypeToken().factory();
    System.out.println(string.getClass().getName());
}
Exception in thread "main" java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl cannot be cast to java.lang.Class
    at com.company.Main$TypeToken.factory(Main.java:19)
    at com.company.Main.execute(Main.java:49)
    at com.company.Main.main(Main.java:55)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by EpicPandaForce on 2015.05.06..
 */
public class Main {
    public static abstract class MyEnum<T> { //typed `enum`-like structure
        public static final MyEnum<String> FOO = new MyEnum<String>(new TypeToken<String>() {}) {};

        protected TypeToken<T> typeToken;

        private MyEnum(TypeToken<T> typeToken) {
            this.typeToken = typeToken;
        }

        public TypeToken<T> getTypeToken() {
            return typeToken;
        }
    }

    public static <T> TypeToken<ArrayList<T>> getListToken(TypeToken<T> typeToken) {
        return new TypeToken<ArrayList<T>> () {};
    }

    public void execute() {
        Gson gson = new Gson();
        List<String> list = gson.fromJson("[]", getListToken(MyEnum.FOO.getTypeToken()).getType()); //construct empty list using GSON
        list.add("hello");
        System.out.println(list.get(0)); //writes out hello
    }

    public static void main(String[] args) {
        Main main = new Main();
        main.execute();
    }
}
public class Main {
    public static abstract class MyEnum<T> {
        public static final MyEnum<String> FOO = new MyEnum<String>(String.class) {};

        protected Class<T> typeToken;

        private MyEnum(Class<T> clazz) {
            this.typeToken = clazz;
        }

        public Class<T> getClazz() {
            return typeToken;
        }
    }

    public static class ListFactory {
        private static Gson gson;

        static {
            gson = new Gson();
        }

        private static <T> TypeToken<ArrayList<T>> getListToken(Class<T> typeToken) {
            return new TypeToken<ArrayList<T>> () {};
        }

        public static <T> List<T> getList(Class<T> clazz) {
            return gson.fromJson("[]", getListToken(clazz).getType());
        }
    }



    public void execute() {
        List<String> list = ListFactory.getList(MyEnum.FOO.getClazz());
        list.add("hello");
        System.out.println(list.get(0));
    }

    public static void main(String[] args) {
        Main main = new Main();
        main.execute();
    }
}
hello
List<MyEnum.FOO.getFooClass()>