我正在使用Java 1.4和Log4J.
我的一些代码涉及序列化和反序列化值对象(POJO).
我的每个POJO都声明了一个记录器
private final Logger log = Logger.getLogger(getClass());
序列化程序抱怨org.apache.log4j.Logger不是Serializable.
我应该用吗?
private final transient Logger log = Logger.getLogger(getClass());
代替?
如何使用静态记录器?或者您是否需要为每个类的实例提供不同的记录器参考?默认情况下,静态字段未序列化; 您可以使用ObjectStreamField
named 的私有静态最终数组显式声明要序列化的字段serialPersistentFields
.请参阅Oracle文档
添加内容:当您使用getLogger(getClass())时,您将在每个实例中使用相同的记录器.如果要为每个实例使用单独的记录器,则必须在getLogger() - 方法中区分记录器的名称.例如getLogger(getClass().getName()+ hashCode()).然后,您应该使用transient属性来确保记录器未序列化.
记录器必须是静态的; 这会使它不可序列化.
除非你有充分的理由这样做,否则没有理由让logger成为非静态的.
如果您真的想要采用瞬态方法,则需要在反序列化对象时重置日志.这样做的方法是实现该方法:
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
Serializable的javadoc 有关于此方法的信息.
您的实现将类似于:
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { log = Logger.getLogger(...); in.defaultReadObject(); }
如果不这样做,则在反序列化对象后,log将为null.
将记录器字段声明为静态或瞬态.
两种方式都确保writeObject()方法在序列化期间不会尝试将字段写入输出流.
通常记录器字段被声明为静态,但是如果您需要它是一个实例字段,则只需将其声明为瞬态,因为它通常用于任何非可序列化字段.在反序列化时,logger字段将为null,因此您必须实现readObject()方法以正确初始化它.