【问题标题】:can I get .class from generic type argument?我可以从泛型类型参数中获取 .class 吗?
【发布时间】:2012-09-21 03:06:31
【问题描述】:

我有以下课程:

public abstract class MyClass<T extends Object> {

    protected T createNewFromData(Reader reader){
        GSON.fromJSON(reader,T.class); // T.class isn't allowed :(
    }
}

如何将 Class 实例传递到那里?是否有一些奇怪而古怪的工作?

除了从 T 类型的预实例化对象之外,还有其他方法可以获取 Class 引用吗?它也不会让我这样做:

T t = new T();
Class<T> klass = t.class;

尝试 #2

有趣的是,如果我从类定义中删除“扩展 JSONOBjBase”,我只会得到一个未经检查的强制转换警告(没有错误)。有没有其他方法可以写出演员是如何完成的?

【问题讨论】:

  • 欢迎来到字体擦除的美妙世界!请参阅 GSON 的 TypeToken。
  • 干杯@SLaks。我根据您的建议用答案更新了我的问题。
  • 我认为该解决方案行不通;我认为TypeToken 必须使用具体类型而不是类型变量创建,并且您确实必须传递类型标记。
  • @LouisWasserman 我还没有运行它,但它编译...:/
  • @MikeS:路易斯是对的。我有理由确定那是行不通的。

标签: java generics gson


【解决方案1】:

没有。
由于类型擦除,此信息在运行时不存在。

相反,您可以重新使用 GSON 的 TypeToken hack,它会创建一个继承封闭通用基类的匿名类。

【讨论】:

    【解决方案2】:

    或者您可以将Class 作为构造函数参数发送并使用该对象而不是尝试获取 T.class。

    public abstract class MyClass<T extends Object> {
    
        private Class<T> klass;
    
        public MyClass(Class<T> klass) {
            this.klass = klass;
        }
    
        protected T createNewFromData(Reader reader){
            GSON.fromJSON(reader,klass); 
        }
    }
    

    【讨论】:

    • 当然可以: public T createNewFormData(Reader reader, Class clazz){ Object a = null; if(clazz.isInstance(a)){ System.out.println("Instance!!"); };返回空值;并这样称呼它:cls.createNewFormData(yourObject, Long.class);
    • 是的,我如何将 Class 传递给 createNewFormData? T.class 不起作用。
    • 这应该是你的方法签名:public T createNewFormData(Reader reader, Class clazz)。当你调用它时,像这样调用它: GSON.fromJSON(reader,clazz);当你调用你的方法时,使用这个:cls.createNewFormData(reader, YourRealClass.class);
    • 为清晰起见进行了编辑。
    【解决方案3】:

    好的。你应该这样做:

          public abstract class MyClass <T> {
    
            public T createNewFormData(Reader reader, Class<T> clazz){
            return GSON.fromJSON(reader, clazz);
            }
          }
    
          public class ImplementMyClass extends MyClass<Long>{
          }
    

    然后这样称呼它:

                MyClass<Long> cls = new ImplementMyClass();
    
    
        Socket s = null;
        try {
            s = new  Socket("localhost", 8080);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        InputStream i = null;
        try {
            i = s.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        InputStreamReader reader = new InputStreamReader(i);
        cls.createNewFormData(reader, Long.class);
    

    【讨论】:

    • 您的第一个代码块在 MyClass.java 中,您的第二个代码块在 MyClassImplementation.java 中。我需要从 MyClass 中调用 createNewFormData - 由于 Java 中泛型的限制,这是不可能的。
    • 第二个块位于任意位置,例如静态 main()。我不明白为什么这对你不起作用,我已经多次使用这种方法。
    • 如果您阅读我的 OP,您会明白为什么它不起作用。我需要从抽象 MyClass 中传入 T 的 T 引用。所以 MyClass 的实现版本指定 'T' 为某物。在 MyClass 中,我想绕过 T.class - 但我不能。
    • OK... GSON.fromJSON(reader, clazz);从抽象类中调用...第二批代码只是显示您应该如何在抽象类中调用您的方法...即使您扩展抽象类,调用仍然有效,它也将是类型-安全。
    • 我不确定你是否明白我在说什么。您正在执行 cls.createNewFormData(reader, Long.class) 并且 Long.class 做得很好,但是我如何从抽象类中执行 T.class?你不能。
    【解决方案4】:

    这与上面Alex给出的答案相呼应。这是一个示例代码,我正在使用 jackson 库编写通用 json -> POJO 包装器:

    /* Method that reads json string from a file, and maps it to an instance of the class passed in as the second argument. */
    
    
    public static <T> T getObjectMappedFromJsonInFile(String fileName, Class<T> clazz){
    
        ObjectMapper mapper=new ObjectMapper();
    
        File file=new File(fileName);
    
        try{
    
            JsonNode jsonNode=mapper.readTree(file);
    
            T response=mapper.convertValue(jsonNode,clazz);
    
            return response;
        }catch (Exception e){
    
            log.error("Error reading transactions.json file",e);
    
        }
        return null;
    
    }
    

    我是这样称呼它的:

    TransactionsResponse response=getObjectMappedFromJsonInFile(fileName,TransactionsResponse.class);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多