Java中LinkedHashMap转Object序列化后变为SQLRow类的问题
问题分析与解决:LinkedHashMap序列化时被识别为SQLRow内部类
问题根源
你在getAsSocketEligibleMap()方法里用了双大括号初始化语法(new LinkedHashMap<>(){{ ... }}),这不是创建原生的LinkedHashMap实例,而是生成了一个LinkedHashMap的匿名内部类,这个类属于SQLRow的内部类,所以类名显示为mirage.database.sql.SQLRow$1。
匿名内部类会隐式持有外部类SQLRow的引用,序列化时不仅需要这个内部类可序列化,接收端也必须有该内部类的定义,这就导致ObjectOutputStream无法将其识别为标准的LinkedHashMap,进而抛出序列化异常。
解决方案
替换双大括号初始化,改用普通的对象创建和填充逻辑,直接返回原生LinkedHashMap实例:
public LinkedHashMap<String, NetworkedSQLObject> getAsSocketEligibleMap(){ LinkedHashMap<String, NetworkedSQLObject> map = new LinkedHashMap<>(); Set<Map.Entry<String, SQLObject>> es = data.entrySet(); Iterator<Map.Entry<String, SQLObject>> i = es.iterator(); while(i.hasNext()){ Map.Entry<String, SQLObject> entry = i.next(); Host.instance.getLogger().info("adding NetworkedSQLObject: " + entry.getKey() + ':' + entry.getValue().getType() + " -> " + entry.getValue().getValue()); map.put(entry.getKey(), new NetworkedSQLObject(entry.getValue())); } return map; }
补充说明
双大括号初始化的本质是:
- 第一层大括号定义了LinkedHashMap的匿名子类
- 第二层大括号是这个子类的实例初始化块
这种写法看似简洁,但会带来额外的内部类实例、外部类引用,以及序列化、内存泄漏等潜在问题,在需要序列化的场景下绝对要避免。
内容的提问来源于stack exchange,提问作者user18514542
相关产品推荐
相关产品推荐

