我有以下方法将文件(包含序列化对象)转换回对象:
public static <T, C extends Class<T>> T readSerializableObjectFromFile(final Path path, final C clazz) {
Objects.requireNonNull(path, "path");
Objects.requireNonNull(clazz, "clazz");
try (ObjectInputStream objectInputStream = new ObjectInputStream(Files.newInputStream(path))) {
return clazz.cast(objectInputStream.readObject());
} catch (IOException ex) {
throw new UncheckedIOException(ex);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(ex);
}
}
假设我有一个Organization
类型的对象,它有equals
和hashCode
方法,写在文件中,当我调用以下内容时会发生什么?
Organization organization =
readSerializableObjectFromFile(myFile, Organization.class);
organization.hashCode()
是否使用Object#hashCode
或Organization#hashCode
实施?
当我在文件中存储List<Organization>
然后通过
@SuppressWarnings("unchecked")
List<Organization> organizations =
readSerializableObjectFromFile(myFile, List.class)
答案 0 :(得分:2)
由于动态调度,每当您调用hashCode()
或任何其他方法的方法时,调用的特定函数取决于对象的运行时类型(而不是声明的类型)对象)。 ObjectInputStream / ObjectOutputStream将保留对象的运行时类型(运行时类是在序列化上编写的,因此用于在反序列化时实例化对象)。
您的强制转换操作只是检查结果的类型是否正确(它不是反序列化数据属于该类型的原因),并且它不会导致数据被转换或截断(如果那是你担心或担心的话)。
对于List&lt; T&gt;,散列方法不依赖于特定类型参数。该类型被删除的事实(无论结构在内部表示的方式如何)都不会改变行为。
答案 1 :(得分:1)
假设我有一个
Organization
类型的对象,它有equals
和hashCode
方法,写在文件中,当我调用以下内容时会发生什么?
当您调用readSerializableObjectFromFile
方法时,将根据文件中的状态创建一个或多个新对象。你重写了hashcode和equals的事实并没有改变这个事实。
organization.hashCode()
是否使用Object#hashCode
或Organization#hashCode
实施?
使用的hashCode()
版本的确定方式完全相同,无论是原始对象还是序列化/反序列化生成的副本。
当我在文件中存储
时,行为是否会发生变化List<Organization>
然后将其检索
不,它没有。
这些问题有点奇怪......
...但也许您缺少的是当您使用Java对象流序列化和反序列化对象时,您得到的是原始对象的副本及其闭包。你没有得到相同的实例......
如果您的课程实施equals
和hashCode
,那么&#34;基于身份的&#34;等于语义,然后复制的对象是不同的对象,因此不相等。但是,如果您的equals
和hashCode
拥有&#34;基于价值的&#34;等式语义,复制的对象应该具有相同的&#34;值&#34; ...
答案 2 :(得分:0)
如何创建对象(直接使用构造函数,反序列化或通过克隆)并不重要。如果此对象的类定义了hashCode
(或equals
),则将使用该方法。