【问题标题】:Gson - In generics how to use type T in fromJson? [duplicate]Gson - 在泛型中如何在 fromJson 中使用类型 T? [复制]
【发布时间】:2021-03-16 10:40:33
【问题描述】:

我正在尝试使用泛型并通过 Gson,尝试反序列化为类型 T。以下是我的代码。

public class Test<T> {
    
    private final Subscriber<T> subscriber;
    Gson gson = new Gson();
    
    public interface Subscriber<T> {
        public void onMessage(T message);
    }
    
    public Test(Subscriber<T> subscriber) {     
        this.subscriber = subscriber;       
    }
    
    public void onResponse(CharSequence data) {
        T responseObj = gson.fromJson(data.toString(), <how to get type of T here>);
        subscriber.onMessage(responseObj);
    }
    
}

正如上面方法onResponse中的代码中提到的,我怎样才能反序列化为T类型的对象?我知道我们可以在构造函数中传递类型并可能使用它。但是还有其他更清洁的方法吗?如果没有,我宁愿把它留给订阅者,不要在这里使用泛型。

有什么想法吗?谢谢

【问题讨论】:

  • 我不知道 Gson,但我认为第二个参数的类型是 Class&lt;T&gt;。假设您只期望T 有一个具体类,您也可以将其传递给构造函数并存储它:Test(Subscriber&lt;T&gt; subscriber, Class&lt;T&gt; type)

标签: java generics gson deserialization


【解决方案1】:

很遗憾,由于type erasure,这是不可能的。在运行时,Java 消除了泛型类型的概念,因此您无法获得对 T.class 的引用。

您可以做的是将Class&lt;T&gt; 传递给Test&lt;T&gt; 的构造函数。虽然它不是最干净的,但它仍然是安全的。

【讨论】:

    【解决方案2】:

    正如其他人所提到的,您不能执行T.class,因为运行时类型擦除并且Java 编译器没有从哪里获取实际类型。但是,fromJson 方法也接受Type 作为其第二个参数,并且Type 可以有各种增强和实现。直接传递Type 实例并不那么安全,因为它没有参数化并且失去了类型控制。传递 Class&lt;T&gt; 是一种缓解措施:它可以在一定程度上保留类型信息,但会丢失类型参数化(例如,Class&lt;List&lt;String&gt;&gt;Class&lt;List&lt;Map&lt;String, Integer&gt;&gt;&gt; 将只是 原始类类型 @987654329 @ -- 如何告诉 Gson 使用哪些泛型?)。我会做以下事情:

    public final class Test<T> {
    
        private static final Gson gson = new Gson();
    
        private final Subscriber<? super T> subscriber;
        private final Type type;
    
        public interface Subscriber<T> {
    
            void onMessage(T message);
    
        }
    
        private Test(final Subscriber<? super T> subscriber, final Type type) {
            this.subscriber = subscriber;
            this.type = type;
        }
    
        public Test(final Subscriber<? super T> subscriber, final TypeToken<? extends T> typeToken) {
            this(subscriber, typeToken.getType());
        }
    
        public void onResponse(final CharSequence data) {
            final T responseObj = gson.fromJson(data.toString(), type);
            subscriber.onMessage(responseObj);
        }
    
    }
    

    在上面的例子中有两个构造函数:

    • 私有一个,用于使用某种类型进行反序列化(私有,因为Type 是 Gson 需要的东西,我们不会暴露我们的内部结构);
    • public 用于从类型令牌中获取类型(并且是公开的,因为我们可以保证从类型令牌中获取正确的Type(假设它没有损坏,当然)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-29
      • 1970-01-01
      • 2020-07-09
      • 1970-01-01
      • 2023-03-15
      相关资源
      最近更新 更多