下面代码中的私有静态final long serialVersionUID = 1L是什么?
public class Authenticator extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("mypassword");
if(authenticate(username, password)) {
HttpSession session = request.getSession();
session.setAttribute("username",username);
response.sendRedirect("product.jsp");
return;
}
else {
response.sendRedirect("index.jsp");
return;
}
}
}
首先,关于这一点有一些快速的提示。
- 在序列化和反序列化过程中起作用。所以对于像
MyCustomRuntimeException
这样你不关心序列化的类,你可以忽略它。 - 如果你为了序列化的目的在类上使用它,但不会在更长的持续时间内存储它们——更具体地说,如果你在存储期间永远不会创建该类的向后不兼容版本,你就不需要更改它。
- 对于您知道将永久存储它并将创建新的不兼容版本的用例,请确保增加(唯一更改)它。
与java.io.Serializable
序列化运行时与每个可序列化类关联一个版本号,称为serialVersionUID,在反序列化期间使用该版本号来验证序列化对象的发送方和接收方是否为该对象加载了与序列化兼容的类。如果接收方为对象加载了一个具有不同于相应发送方类的serialVersionUID的类,那么反序列化将导致InvalidClassException。一个可序列化的类可以通过声明一个名为"serialVersionUID"的字段显式地声明它自己的serialVersionUID。它必须是静态的、final的、long类型的:ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L
如果可序列化类没有显式声明serialVersionUID,那么序列化运行时将根据该类的各个方面计算该类的默认serialVersionUID值,如Java(TM)对象序列化规范中所述。然而,强烈建议所有可序列化的类显式声明serialVersionUID值,因为默认的serialVersionUID计算对类细节非常敏感,这些细节可能因编译器实现而有所不同,因此可能在反序列化期间导致意外的InvalidClassExceptions。因此,为了保证在不同的java编译器实现中具有一致的serialVersionUID值,可序列化的类必须声明显式的serialVersionUID值。还强烈建议显式serialVersionUID声明尽可能使用私有修饰符,因为这样的声明只适用于立即声明的类——serialVersionUID字段作为继承成员是没有用的。数组类不能声明一个显式的serialVersionUID,所以它们总是有默认的计算值,但是数组类不需要匹配serialVersionUID值。
From Joshua Bloch in有效的Java
自动生成的UID是基于类名、实现的接口以及所有公共和受保护成员生成的。以任何方式改变这些都会改变serialVersionUID。但是,强烈建议所有可序列化的类显式声明serialVersionUID值,因为默认的serialVersionUID计算对类细节非常敏感,这些细节可能因编译器实现而有所不同,并且可能在不同的环境中产生不同的serialVersionUID。这可能会在反序列化期间导致意外的InvalidClassException。因此,为了保证在不同的java编译器实现中具有一致的serialVersionUID值,可序列化的类必须声明显式的serialVersionUID值。还强烈建议显式serialVersionUID声明尽可能使用serialVersionUID中的私有修饰符,因为这样的声明仅适用于立即声明的类。