先放一段代码 显然List 里放入多种子类的话 子类类型会丢失 但是项目里有时候会有需求要把子类的信息完整得还原出来 实现思路如下: 在父类的最顶层里加一个classInfo,去标明类信息,子类都继承这个父类,然后序列化的时候拿map去接收 最后将map 当做一颗树 ,map如果带classInfo 就将他转化成classInfo的类,如果map里面还有map同理,层层递归 如果这个map已经被转成对象 那么他会被记在map里key是map value是map对应的对象 循环引用时取对象的hashcode会报错,所以用map当key会栈溢出 (最后放栈溢出的代码) 所以用System.identityHashCode(map) (可以看作map的内存地址)来当key 核心代码如下 map入参如下: 转化后 栈溢出的代码如下: 反射工具类代码 对时间做了下特殊处理 缓存了反射的方法信息
public class Test { public static void main(String[] args) { //建立一个数组 第一个放入child 第二个放入parent List<Parent> list = new ArrayList<>(); Parent parent = new Parent(); parent.setX("1"); Child child = new Child(); child.setX1("1"); list.add(child); list.add(parent); String json = JSON.toJSONString(list); List<Parent> list1 = JSON.parseArray(json, Parent.class); //强转失败 Child child1 = (Child) list1.get(0); } }
当然要考虑对象循环引用不能死递归的问题:
/** * 对参数做树递归 有条件用栈做 * * @param object * @param remember * @return */ private static Object map2Class(Object object, Map<Integer, Object> remember) { if (object instanceof List) { List obj = new ArrayList(); List list = (List) object; list.forEach(i -> { obj.add(map2Class(i, remember)); }); return obj; } else if (object instanceof Map) { Map<String, Object> map = (Map<String, Object>) object; Object classInfo = map.remove("className"); Object o = null; if (classInfo == null) { return Optional.ofNullable(remember.get(System.identityHashCode(map))).orElseGet( () -> { for (Map.Entry<String, Object> entry : map.entrySet()) { map.put(entry.getKey(), map2Class(entry.getValue())); } return map; } ); } else { try { Class<?> aClass = Class.forName(classInfo.toString()); o = aClass.getDeclaredConstructor().newInstance(); remember.put(System.identityHashCode(map), o); } catch (Exception e) { e.printStackTrace(); } } for (Map.Entry<String, Object> entry : map.entrySet()) { if (entry.getValue() != null) { Object o1 = map2Class(entry.getValue(), remember); reflectUtil.setProperty(o, entry.getKey(), o1); } } return o; } else { return object; } } /** * 调用类 * @param object * @param <T> * @return */ public static <T> T map2Class(Object object) { Map<Integer, Object> map = new HashMap<>(); Object o = map2Class(object, map); return (T) o; }
public static void main(String[] args) { Map<String,Map> map=new HashMap<>(); Map<String,Map> map1=new HashMap<>(); map.put("1",map1); map1.put("1",map); Set<Map> set=new HashSet<>(); //栈溢出底层用了hashcode set.add(map); }
public class GetSetterReflectUtil { private final static Logger logger = LoggerFactory.getLogger(GetSetterReflectUtil.class); private static WeakHashMap<SoftReference<String>, Map<String, Tuple3<Class, Method, Method>>> methodWeakHashMap = new WeakHashMap<>(); private static Map<Class, Function<Object, Object>> classFunctionMap = new HashMap<>(); static { classFunctionMap.put(Date.class, (o) -> { if (o instanceof Long) { o = new Date((Long) o); } if (o instanceof String) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS"); Date parse = null; try { parse = sdf.parse(o.toString()); return parse; } catch (ParseException e) { logger.error("时间转化出现错误 格式不匹配 value[{}]", o); } } return o; }); } private static Map<String, Tuple3<Class, Method, Method>> getClassMethod(Object beanObj) { Class<?> aClass = beanObj.getClass(); String clazzName = aClass.getName(); PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(beanObj.getClass()); Map<String, Tuple3<Class, Method, Method>> map = new HashMap<>(); for (PropertyDescriptor descriptor : propertyDescriptors) { String name = descriptor.getName(); Method readMethod = descriptor.getReadMethod(); Method writeMethod = descriptor.getWriteMethod(); map.put(name, Tuple3.of(descriptor.getPropertyType(), readMethod, writeMethod)); } SoftReference<String> softReference = new SoftReference<String>(clazzName); methodWeakHashMap.put(softReference, map); return map; } public Object invokeMethod(Object beanObj, String methodName, String type, Object param) { Class<?> aClass = beanObj.getClass(); String clazzName = aClass.getName(); SoftReference<String> softReference = new SoftReference<String>(clazzName); Map<String, Tuple3<Class, Method, Method>> methodMap = methodWeakHashMap.get(softReference); if (methodMap == null) { methodMap = getClassMethod(beanObj); methodWeakHashMap.put(softReference, methodMap); } Tuple3<Class, Method, Method> tuple3 = methodMap.get(methodName); try { Method method = "R".equals(type) ? tuple3.getT() : tuple3.getValue(); if (method == null) { logger.error("未找到 name=[{}]的方法", methodName); } else { method.setAccessible(true); Function<Object, Object> function = classFunctionMap.get(tuple3.getKey()); if (function != null) { param = function.apply(param); } return method.invoke(beanObj, param); } } catch (Exception e) { logger.error("执行 name=[{}] kClass=[{}] value=[{}] 的方法出错 {}", methodName, tuple3.getKey(), param, e); throw new RuntimeException(e); } return null; } /* 该方法用于传入某实例对象以及对象方法名,通过反射调用该对象的某个get方法 */ public Object getProperty(Object beanObj, String methodName) { try { return invokeMethod(beanObj, methodName, "R", null); } catch (Exception e) { e.printStackTrace(); } return null; } /* 该方法用于传入某实例对象以及对象方法名、修改值,通过放射调用该对象的某个set方法设置修改值 */ public void setProperty(Object beanObj, String methodName, Object value) { if (beanObj == null || methodName == null || value == null) { return; } try { invokeMethod(beanObj, methodName, "W", value); } catch (Exception e) { logger.error("执行set出现错误 [{}]", e); } } }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算