Gson反序列化Java泛型抛出UnsupportedOperationException解决方法
问题原因
异常的核心原因是泛型参数传参与逻辑设计不匹配:
你调用addStompClient时传入的第一个参数是Category.class,这个对象本身的类型是Class<Category>,会让泛型T被推导为java.lang.Class,而非你预期的Category业务类。后续在onMessage方法中执行t.getClass()时,拿到的是java.lang.Class的类型对象,Gson尝试将业务JSON反序列化为Class类实例时,就会抛出你看到的类型适配器缺失异常。
修复步骤
直接调整参数定义和类型存储逻辑即可,不需要额外给Gson注册Class类型的适配器:
- 修改
addStompClient方法签名,将第一个参数的类型从泛型实例T改为字节码类型Class<T>
public <T> void addStompClient(Class<T> tClass, String url, String subscription, StompMessageListener<T> listener) { StompClient<T> sc = new StompClient<T>(tClass, URI.create(url)); StompConnectionListener scl = new StompConnectionListener() { public void onConnecting() {} public void onConnected() { sc.subscribe(subscription, listener); } public void onDisconnected() {} }; sc.setStompConnectionListener(scl); sc.connect(); clients.add(sc); }
- 修改
StompClient类的成员变量和构造方法,直接存储传入的字节码对象,不再存储泛型实例
@Getter private Class<T> tClass; protected StompClient(Class<T> tClass, URI serverUri) { super(serverUri); this.tClass = tClass; }
- 简化
onMessage中的反序列化逻辑,直接使用存储的字节码对象做JSON转换,去掉冗余的getClass()调用和强转
case MESSAGE: Integer subscriptionId = Integer.valueOf(stompFrame.getHeaders().get(StompHeader.SUBSCRIPTION.toString())); // 直接用存储的tClass反序列化,不需要再取getClass() T test = new Gson().fromJson(stompFrame.getBody(), tClass); StompSubscription<T> listener = (StompSubscription<T>) subscriptions.get(subscriptionId); listener.getListener().onMessage(test); break;
修改完成后原有调用代码不需要调整,传入Category.class时,泛型会被正确推导为Category类型,反序列化得到的对象可以直接调用getName()等业务方法,不会再抛出异常。
内容的提问来源于stack exchange,提问作者Sean Rahman
相关产品推荐
相关产品推荐

