Gson -在泛型中如何在fromJson中使用类型T?[duplicate]

flmtquvp  于 2022-11-23  发布在  其他
关注(0)|答案(2)|浏览(213)

此问题在此处已有答案

Using a generic type with Gson(3个答案)
How do I get a class instance of generic type T?(23个答案)
去年关闭了。
我尝试使用泛型并通过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的对象?我知道我们可以在构造函数中传递该类型,也许可以使用它。但是有没有其他更干净的方法?如果没有,我宁愿把它留给订阅者,这里不使用泛型。
有什么想法吗?谢谢

pzfprimi

pzfprimi1#

不幸的是,由于type erasure,这是不可能的。在运行时,Java删除了泛型类型的概念,因此您无法获得对T.class的引用。
你可以把一个Class<T>传递给Test<T>的构造函数,虽然它不是最干净的,但仍然是安全的。

wgxvkvu9

wgxvkvu92#

正如其他人所提到的,您不能执行T.class,因为在运行时会擦除类型,Java编译器无法从何处获取实际类型。然而,fromJson方法也接受Type作为其第二个参数,并且Type可以有各种增强和实现。直接传递Type示例并不安全,因为它没有被参数化并且失去了类型控制。它可以在一定程度上保留类型信息,但是它丢失了类型参数化(例如,Class<List<String>>Class<List<Map<String, Integer>>>将只是 raw class typeList.class--如何告诉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);
    }

}

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

  • private一个用于使用 some type 从反序列化(private是因为Type是Gson需要的,我们不公开我们的内部);
  • public一个,用于从类型标记中获取类型(之所以是public,是因为我们可以保证从类型标记中获取正确的Type(假设它没有损坏,当然))。

相关问题