我是靠谱客的博主 开心舞蹈,最近开发中收集的这篇文章主要介绍java list存储错乱,【bug】 -- List.subList()未序列化导致Redis报错,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

别人遇到的bug,收集起来以防自己同样犯错。

bug产生的场景:

项目中对文章的详情内容通过Redis做了缓存,详情中以List形式关联了一些其他内容。在Redis中存储数据也将会是从业务中获取的List集合。存储数据要求3条即可,但是查询接口返回的数据不一定为3条,当多于3条是,就需要截取,在截取的过程中使用了list.subList(0,3),来获取其中3条数据。之后就报错了。。。 (由于这块业务的负责人是另一位同事,自己没有看到异常信息,无法截图,故遇到时能够想起即可)

原错误代码:

3c13de60d4f763ebb1216db21402a1e1.png

分析:

切割后的存储形式应该就变成了java.util.ArrayList$SubList,这种格式的对象从Redis中拿出来是没法进行反序列化的。原因是list接口并没有实现序列化。在jdk6中,ListsubList(int fromIndex, int toIndex)返回的是没有实现Serializable接口的java.util.RandomAccessSubList。在其父类或者接口中都找不到Serializable这个标志。而在jdk7和8中,sublist实现,它是在ArrayList中直接搞了一个私有内部类:private class SubList extends AbstractListimplements RandomAccess,而jdk6中class RandomAccessSubListextends SubListimplements RandomAccess,注意这里的SubList跟上面的是不同的,这里的SubList是AbstractList的内部类。

综上,ArrayList.subList方法返回的对象是一个sublist类型的视图,这个sublist类型的是ArrayList的一个内部类,不支持序列化。视图的含义就是它里面的元素数量变了,但是操作其中的元素实际上还是操作的原来的list,并不是新的那份list。如果改变原有的list,那么就会抛出ConcurrentModificationException异常。即:

fdaafad4b88c117dfd0f13a6e9e756ad.png

就算未对原有list进行修改,但是因其未做序列化,从Redis中读取数据时会因无法反序列化而出现问题。

解决方案:

1.重新创建一个可以实现序列化的list集合,将截取后的list存入,实现序列化

List list = new ArrayList(imgList.subList(0,3));

jsonRelatedArticles.setImgList(list);

or

ListserializedList= new ArrayList();

serializedList.addAll(sublist);

//在这里就是,其实跟上边一种大同小异

ListserializedList= new ArrayList<>();

serializedList.addAll(imgList.subList(0,3));

jsonRelatedArticles.setImgList(serializedList);

2.避免使用subList,使用循环遍历一个个add。

if (a.getImgList() != null && a.getImgList().size() >= 3){

ListimgList = new ArrayList<>(3);

for (int i = 0; i < 3; i++){

JsonArticleDetail.JsonImg jsonImg = new JsonArticleDetail.JsonImg();

jsonImg.setUrl(imageUtil.getCommonImageUrl(a.getImgList().get(i).getImgPath()));

imgList.add(jsonImg);

}

}

//注意a.getImgList().get(i).getImgPath()可能会有空指针异常,本代码只简要表明重点,视情况判断。

3.其实单针对于本次错误代码而言,只需要在原有循环上简单修改即可。如下:

e9ce4af563f71e162e63d40c48132b39.png

综上:

发现简单一个subList就有很大的陷阱,所以基础知识还是需要牢固。

附:java.util.List.subList使用注意

redis数据存储形式:

ridis大方面来说,就是一个K-V数据库,用于存储数据,这个数据库也可以存储复杂结构的数据,像有关的集合数据,所以它也具备了对复杂数据的高效查询,(故障恢复特性,文件有关数据持久化能力)

数据跨平台存储通过网络的传输层进行传输,所以必须序列化

最后

以上就是开心舞蹈为你收集整理的java list存储错乱,【bug】 -- List.subList()未序列化导致Redis报错的全部内容,希望文章能够帮你解决java list存储错乱,【bug】 -- List.subList()未序列化导致Redis报错所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部