Java泛型getData方法如何替代类名字符串switch,优化多类型返回实现
可行实现方案(按推荐度排序)
方案1:Class映射注册表(无反射、类型安全、扩展性最强)
核心思路是预先把所有支持的返回类型,和对应的JSON转实例逻辑注册到Map里,直接用Class对象作为查询键,完全消除字符串匹配和硬编码分支:
// 静态注册所有支持的类型转换规则,新增类型只需要加一行条目即可 private static final Map<Class<?>, Function<JSONObject, ?>> TYPE_CONVERTER = Map.of( Profile.class, json -> new Profile(json.getString("nickname"), json.getInt("level"), /* 自定义参数 */), UserVideo.class, json -> new UserVideo(json.getLong("vid"), json.getString("playUrl"), /* 自定义参数 */) ); public <T> T getData(final Class<T> cast, final String query) { final Optional<JSONObject> optional = Optional.ofNullable(new JSONObject(getHTTP(query))) .filter(s -> s.has("data") && s.getJSONArray("data").length() > 0 && s.getJSONArray("data").get(0) instanceof JSONObject); if (optional.isPresent()) { final JSONObject dataJson = optional.get().getJSONArray("data").getJSONObject(0); Function<JSONObject, ?> converter = TYPE_CONVERTER.get(cast); if (converter != null) { // 直接用cast做类型转换,安全无警告 return cast.cast(converter.apply(dataJson)); } } return null; }
方案优势:
- 完全符合开闭原则,新增类型不需要修改
getData核心逻辑 - 无反射性能损耗,构造参数可以灵活自定义,适配不同类的特殊构造规则
- 调用方式完全和你原有写法一致,无侵入性
方案2:JSON自动反序列化(适合JSON字段和类字段完全匹配的场景)
如果你的业务类字段名和JSON返回的key完全对应,不需要自定义构造逻辑,可以直接用JSON库自带的反序列化能力,一行代码完成转换,不需要为每个类写单独的逻辑:
// 以Fastjson为例,Gson/Jackson也有完全等价的API public <T> T getData(final Class<T> cast, final String query) { final Optional<JSONObject> optional = Optional.ofNullable(new JSONObject(getHTTP(query))) .filter(s -> s.has("data") && s.getJSONArray("data").length() > 0 && s.getJSONArray("data").get(0) instanceof JSONObject); return optional.map(json -> json.getJSONArray("data").getJSONObject(0).toJavaObject(cast)) .orElse(null); }
如果要自己实现反射注入逻辑也可以:
public <T> T getData(final Class<T> cast, final String query) throws Exception { final Optional<JSONObject> optional = Optional.ofNullable(new JSONObject(getHTTP(query))) .filter(s -> s.has("data") && s.getJSONArray("data").length() > 0 && s.getJSONArray("data").get(0) instanceof JSONObject); if (optional.isPresent()) { JSONObject dataJson = optional.get().getJSONArray("data").getJSONObject(0); // 调用无参构造实例化 T instance = cast.getDeclaredConstructor().newInstance(); // 反射遍历字段赋值 for (Field field : cast.getDeclaredFields()) { field.setAccessible(true); field.set(instance, dataJson.get(field.getName())); } return instance; } return null; }
方案3:Java 17+ 类型Pattern匹配(语法层面支持Class对象Switch)
如果你使用Java 17及以上版本,原生已经支持直接在Switch分支里匹配Class类型,不需要转字符串做匹配:
public <T> T getData(final Class<T> cast, final String query) { final Optional<JSONObject> optional = Optional.ofNullable(new JSONObject(getHTTP(query))) .filter(s -> s.has("data") && s.getJSONArray("data").length() > 0 && s.getJSONArray("data").get(0) instanceof JSONObject); if (optional.isPresent()) { final JSONObject dataJson = optional.get().getJSONArray("data").getJSONObject(0); return switch (cast) { case Class<Profile> clazz -> clazz.cast(new Profile(/* 构造参数 */)); case Class<UserVideo> clazz -> clazz.cast(new UserVideo(/* 构造参数 */)); default -> null; }; } return null; }
内容的提问来源于stack exchange,提问作者Girls are beautiful
相关产品推荐
相关产品推荐

