Kotlin泛型Retrofit函数调用抛出ClassCastException问题排查
问题根源与解决方案
核心原因
这个错误的本质是泛型类型擦除导致的:Java在运行时会擦除泛型的具体类型信息,Retrofit和Gson无法得知你指定的Standings类型,只能将JSON响应默认解析成LinkedTreeMap(Gson处理未知类型的默认行为)。当你尝试把这个LinkedTreeMap强制转换成retrofit2.Response<Standings>时,就会触发ClassCastException。
常见的错误场景包括:
- 接口定义了泛型方法,但没有提供足够的类型信息让Retrofit/Gson识别目标类型
- 错误地将接口返回值强转为不匹配的泛型类型
- 接口方法的返回值类型定义模糊(比如用
Call<Object>代替Call<Response<Standings>>)
修复方案
方案1:为每个实体类定义独立接口方法(推荐)
直接避免泛型擦除问题,明确指定每个接口方法的返回类型:
public interface LeagueApi { // 获取Standings类型的响应 @GET("standings") Call<Response<Standings>> getLeagueStandings(); // 获取Standings2类型的响应 @GET("standings") Call<Response<Standings2>> getLeagueStandings2(); }
调用时无需指定泛型,Retrofit会直接根据方法定义解析出正确的实体类实例:
leagueApi.getLeagueStandings().enqueue(new Callback<Response<Standings>>() { @Override public void onResponse(Call<Response<Standings>> call, retrofit2.Response<Response<Standings>> response) { if (response.isSuccessful()) { Response<Standings> standingsResponse = response.body(); // 正常处理Standings实例 } } @Override public void onFailure(Call<Response<Standings>> call, Throwable t) { // 处理错误 } });
方案2:使用接口级泛型(适合复用逻辑场景)
如果需要复用接口逻辑,可以将泛型定义在接口级别,创建实例时指定具体类型:
public interface LeagueApi<T> { @GET("standings") Call<Response<T>> getLeagueStandings(); }
创建接口实例时明确传入Standings类型:
LeagueApi<Standings> standingsApi = retrofit.create(LeagueApi.class); standingsApi.getLeagueStandings().enqueue(new Callback<Response<Standings>>() { // 回调逻辑同方案1 });
方案3:显式传递类型信息(复杂泛型场景)
如果必须使用泛型方法,需要通过TypeToken显式告诉Gson目标类型。这种方式需要手动解析响应体:
// 定义泛型方法,返回原始ResponseBody public interface LeagueApi { @GET("standings") Call<ResponseBody> getLeagueStandings(); }
调用时手动解析,用TypeToken明确泛型类型:
leagueApi.getLeagueStandings().enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) { if (response.isSuccessful()) { try { String json = response.body().string(); // 用TypeToken指定Response<Standings>的具体类型 Type type = new TypeToken<Response<Standings>>(){}.getType(); Response<Standings> standingsResponse = new Gson().fromJson(json, type); // 处理实例 } catch (IOException e) { e.printStackTrace(); } } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { // 处理错误 } });
内容的提问来源于stack exchange,提问作者Ahmed Gamal
相关产品推荐
相关产品推荐

