自从最近迁移到Java 10以来,我们还考虑在代码库中用Joda-Time类替换java.time。最大的障碍是如何处理现有的序列化Java对象,这些对象具有Joda-Time数组(例如LocalDate
,Period
)作为字段。
项目中使用的Joda-Time版本是自定义版本,即。我们可以完全控制它。我试图在Joda-Time readObject
中提供LocalDate
实现,以使其返回Java LocalDate
。但是,如果LocalDates包含在一个数组中(从ArrayStoreException
的{{1}}方法抛出readArray
的数组中,这是行不通的,因为LocalDate的本地版本是Java版本)。
ObjectInputStream
我什至试图对// code taken from ObjectInputStream
Object array = null;
Class<?> cl, ccl = null;
if ((cl = desc.forClass()) != null) {
ccl = cl.getComponentType(); // ccl is java LocalDate.class
array = Array.newInstance(ccl, len);
}
...// intermediate code ignored
Object[] oa = (Object[]) array;
for (int i = 0; i < len; i++) {
oa[i] = readObject0(false); // ArrayStoreException thrown here, readObject0 returns a joda LocalDate
handles.markDependency(arrayHandle, passHandle);
}
进行子类化,以使其解析为Java ObjectInputStream
,以防它反序列化joda LocalDate。由于JVM检测到序列化的LocalDate与解析的序列号没有相同的serialVersionUID,因此它不起作用(由于Java LocalDate具有不同的UID,因此显然是正确的)。在突破的直截了当的想法中,我尝试通过反射和覆盖LocalDate.class
的{{1}}使两者返回相同的UID。但是后来又发生了新的异常。使事情变得复杂的是,Java时间序列化是由Ser.class以readClassDescriptor
的方式完成的,与joda time不同。而且ObjectInputStream对它们的处理方式不同。所以现在我被卡住了。
在对ObjectInputStream进行子类化之前,我想听更多的人关于您对此类问题的想法/经验,或者从技术上讲如何反序列化更改后的数组对象版本。顺便说一句,我非常怀疑我是否能够以正确的方式解决我所面临的问题,即能够读取现有的序列化对象。
示例代码:
ObjectInputStream
首先运行上面的代码以生成一个ser文件。然后,注释对方法Externalizable
的调用,并用java LocalDate替换joda LocalDate。再次运行该代码,您将得到一个ClassCastException,它表示它正在尝试将org.joda.time.LocalDate转换为java.time.LocalDate。我们可以通过将ObjectInputStream子类化并重写readObject方法来返回java LocalDate来解决这个问题,以防反序列化joda。
import org.joda.time.LocalDate;
import java.io.Serializable;
import java.util.Arrays;
public class DemoObject implements Serializable {
private static final long serialVersionUID = 1L;
private LocalDate[] dates;
public DemoObject(LocalDate[] dates) {
this.dates = dates;
}
@Override
public String toString() {
return Arrays.asList(dates).toString();
}
}
///////////////////////////////////////////////////////////////////
import org.joda.time.LocalDate;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.util.List;
public class SerializationDemo {
public static void main(String[] args) throws Exception {
LocalDate[] dates = new LocalDate[2];
for (int i=0; i<dates.length; i++) {
dates[i] = new LocalDate().minusDays(i);
}
DemoObject demoObject = new DemoObject(dates);
serialize(demoObject);
deserialize(getSerialFileName(demoObject));
}
private static void serialize(Object demoObject) throws IOException {
try(ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(getSerialFileName(demoObject)))) {
out.writeObject(demoObject);
}
}
private static Object deserialize(String fileName) throws IOException, ClassNotFoundException {
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName))) {
Object demoObject = in.readObject();
System.out.println(demoObject);
return demoObject;
}
}
}
但是,构造反序列化的数组对象时,将引发ArrayStoreException。
serialize(demoObject);
如何解决数组问题?