匿名内部类方式构建对象导致序列化失败

简介: ###问题描述: 以下代码为问题代码: ``` public class ItemDO implements Serializable { private static final long serialVersionUID=-463144769925355007L; ... private Map langAndTitleMap; ...

问题描述:

以下代码为问题代码:

public class ItemDO implements Serializable {

    private static final long serialVersionUID=-463144769925355007L;
    
    ...
    
    private Map<String,String> langAndTitleMap;
    
    ...
}
public class ItemMultiLangDecorator implements ItemDecorator {
    
    ...

     @Override
    public ItemDO getItemDO() throws IcException {
        ...
        
        if(titleMultiLangFieldMeta!=null){
            itemDO.setLangAndTitleMap(new HashMap<String, String>(){{put(titleMultiLangFieldMeta.getFieldLang(),itemDO.getTitle());}});
        }else{
            itemDO.setLangAndTitleMap(new HashMap<String, String>(){{put(LanguageConstants.EN,itemDO.getTitle());}});
        }
        
        ...
    }

    ...
} 

在应用发布之后,日志出现ItemDO类序列化报错异常,如下:

java.io.NotSerializableException: com.taobao.item.manager.decorator.ItemMultiLangDecorator
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
        at com.taobao.item.util.CloneUtil.deepCloneBySerialize(CloneUtil.java:29)
        at com.taobao.item.domain.ItemUpdateDO.mergeDbItem(ItemUpdateDO.java:320)

问题原因

虽然序列化的是ItemDO类,但是报错却是ItemMultiLangDecorator类,表面上看ItemDO里面并无任何对ItemMultiLangDecorator引用,但是由于在构造HashMap实例时候采用了匿名内部类构造的方式,即{{ ... }}形式,查阅资料得知道java会在匿名内部类的实例都持有一个外部封装类实例的隐式引用,也就导致构建Map实例拥有所在外部类ItemMultiLangDecorator实例引用,而恰好外部类并没有实现序列化接口。

本人也在本地写了一个Demo再次重现该问题。

public class Inner implements Serializable{

    private static final long    serialVersionUID= -463144769925355007L;
    
    private String name;

    public void setName(String name) {
        this.name = name;
    }
}
public class Outer {

    public Inner create(){
        return new Inner(){
            {
                setName("Hello");
            }
        };
    }

}
public class Main {

    public static void main(String[] args) {
        Inner inner=new Outer().create();

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(baos);
            oos.writeObject(inner);
            oos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

运行后会抛出Outer类序列化错误,在IDE中断点,可以看到Inner类持有外部类实例引用,如图:
image.png

目录
相关文章
|
1月前
|
JSON Java API
GSON 泛型对象反序列化解决方案
GSON 泛型对象反序列化解决方案
|
3月前
|
分布式计算 Java 大数据
IO流【Java对象的序列化和反序列化、File类在IO中的作用、装饰器模式构建IO流体系、Apache commons-io工具包的使用】(四)-全面详解(学习总结---从入门到深化)
IO流【Java对象的序列化和反序列化、File类在IO中的作用、装饰器模式构建IO流体系、Apache commons-io工具包的使用】(四)-全面详解(学习总结---从入门到深化)
53 0
|
1月前
|
JSON Android开发 数据格式
android 使用GSON 序列化对象出现字段被优化问题解决方案
android 使用GSON 序列化对象出现字段被优化问题解决方案
|
2月前
|
vr&ar
MFC序列化及反序列化对象
MFC序列化及反序列化对象
18 0
|
3月前
|
存储 JSON 运维
PowerShell 对象的序列化和反序列化
PowerShell 对象的序列化和反序列化
36 0
|
4月前
|
缓存 NoSQL Java
Spring Data Redis对象缓存序列化问题
在使用 Redis 时,有没有遇到同我一样,对象缓存序列化问题的呢?
67 6
Spring Data Redis对象缓存序列化问题
|
4月前
|
存储 Java
对象序列化流和对象反序列化流
对象序列化流和对象反序列化流
45 0
|
4月前
|
XML 存储 JSON
C# | 使用Json序列化对象时忽略只读的属性
将对象序列化成为Json字符串是一个使用频率非常高的功能。Json格式具有很高的可读性,同时相较于XML更节省空间。 在开发过程中经常会遇到需要保存配置的场景,比如将配置信息保存在配置类型的实例中,再将这个对象序列化成为Json字符串并保存。当需要加载配置时,则是读取Json格式的字符串再将其还原成配置对象。在序列化的过程中,默认会将所有公开的属性和字段都序列化进入Json字符串中,这其中也会包含只读的属性或字段,而只读的属性和字段在反序列化的过程中其实是无意义的,也就是说这一部分存储是多余的。 本文将讲解如何在执行Json序列化时,忽略掉那些只读的属性和字段。
54 0
C# | 使用Json序列化对象时忽略只读的属性
|
5月前
|
缓存 安全 网络协议
对象的序列化与反序列化详解
对象的序列化与反序列化详解
49 0
对象的序列化与反序列化详解
|
6月前
|
XML JavaScript 前端开发
SAP UI5 Fiori Elements annotation 文件序列化成 DOM 对象的逻辑
SAP UI5 Fiori Elements annotation 文件序列化成 DOM 对象的逻辑
29 0

热门文章

最新文章