如果你的对象需要网络传输或者持久化(对象直接转换为字节的形式传输),那么就需要实现Serializable接
口。为了防止反序列失败,该对象需提供一个默认的serialVersionUID(该值在反序列化的时候会进行校验,
如果校验失败会抛异常-InvalidClassException)。
提问:现在需要将一个对象返回给前端,那么该对象是否需要实现 Serializable接口,并提供一个默认的serialVersionUID,如果不实现会有什么影响?
我们现在想一个问题,现在一般前后端进行数据交互一般都是json格式 (json格式数据其实就是String) 的数据,那么是谁在什么时候将我们的对象转换成json格式的?只要想明白这个问题,也就解决了我们提出的疑问。
这里我先用SpringMVC框架做一番解释,我们使用SpringMVC框架的时候如果要返回一个json串给前端只需要将对象返回并且在方法上加上@ResponseBody注解,类似以下操作:
SpirngMVC又是在什么时候由哪个类处理@ResponseBody这个注解的呢?
SpringMVC 中处理@ResponseBody主要是通过类:RequestResponseBodyMethodProcessor#handleReturnValue处理返回值,解析成json又涉及到的HttpMessageConverter的配置,其实正常情况下SpringMVC是自动帮我们配置以下转换器:
① ByteArrayHttpMessageConverter
② StringHttpMessageConverter
③ ResourceHttpMessageConverter
④ SourceHttpMessageConverter
⑤ AllEncompassingFormHttpMessageConverter
是否引入jackson包配置MappingJackson2HttpMessageConverter。
具体详见WebMvcConfigurationSupport#addDefaultHttpMessageConverters。一般执行解析操作的是MappingJackson2HttpMessageConverter这个类,其实这个类不是干实事的,具体操作还得交给ObjectMapper这个类取实现。而ObjectMapper就是jackson包中的一个类。
jackson是怎么将对象转换成json的?
jackson将对象解析成json的入口是ObjectMapper#writeValueAsString,其内部实现大概是先初始化一个4000容量的WriterBasedJsonGenerator#_outputBuffer char数组,然后将对象中的字段一一往char数组中放入,最后将char数组转换成String。具体详见ObjectMapper#writeValueAsString,因此对象转换成json与Serializable无关。
验证:
如果一个对象进行序列化跟实现Serializable有关系的话,那么序列化的过程中一定就会调用该对象下的writeObject(java.io.ObjectOutputStream s) ,因此只需启动程序调用接口,在方法writeObject上打断点,看是否可以拦截住。这里使用HashSet做实验。会发现断点没有停住。说明使用SpringMVC框架返回给前端的对象无需实现Serializable接口,其大致图如下:
因此真正与网络传输打交道的是SpringMVC转换后的json字符串,实体对象与网络并没用直接的接触,所以这里的实体对象无需实现Serializable接口。
总结:
一般来说如果你的对象需要网络传输或者持久化 (对象直接转换为字节的形式传输),那么就需要实现Serializable接口。比如远程方法调RPC (Remote Procedure Call) 则接口参数就一定要实现Serializable接口;如果只是转换为json字符串的形式与网络打交道,那么就不需要实现Serializable接口。
实体对象实现了java.io.Serializable接口后,一般都会提供一个serialVersionUID以做版本区分。在idea里,可以通过设置来快速生成serialVersionUID。
1、打开Preferences–>Editor–>Inspections,然后在右侧输入UID进行搜索(搜索方式比较快,也可以在java–>Serialization issues里找)。然后勾选Serializable class without 'serialVersionUID’后面的复选框。右侧Severity默认Warning即可。如下图:
2、测试,新建一个实体Student,实现java.io.Serializable接口,然后将光标放到类名Student上,按option+return(window按alt+enter,快捷键可能不一样,根据自己的设置来)打开提示框,选择Add ‘serialVersionUID’ field确定即可,如下图: