NotSerializableException
异常
@Data
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
public static int id;
private String name;
private int age;
// 参与序列化的类也必须能序列化,否则会报 NotSerializableException
private Pet pet;
private transient Car car;
private int height;
public static void main(String[] args) {
serializePerson();
deserializePerson();
}
private static void serializePerson() {
Person person = new Person();
person.setName("张三三");
person.setAge(18);
person.setPet(new Pet("大黄"));
person.setCar(new Car("奥迪"));
Person.id = 1;
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("person.txt"))) {
out.writeObject(person);
System.out.println("序列化完成");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("JSON.toJSONString(person):"+JSON.toJSONString(person));
}
private static void deserializePerson() {
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("person.txt"))) {
Person readObject = (Person) in.readObject();
System.out.println("readObject = " + readObject);
System.out.println(Person.id);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Data
public class Car {
private String name;
public Car(String name) {
this.name = name;
}
}
@Data
public class Pet implements Serializable {
private String name;
public Pet(String name) {
this.name = name;
}
}
序列化完成
JSON.toJSONString(person):{"age":18,"height":0,"name":"张三三","pet":{"name":"大黄"}}
readObject = Person(name=张三三, age=18, height=0, pet=Pet(name=大黄), car=null)
1
说明:
静态成员变量不能序列化(序列化)
transient修饰的成员变量不参与序列化
参与序列化的引用类型也必须实现Serializable接口,否则会报NotSerializableException异常
@Data
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private Pet pet;
public static void main(String[] args) throws CloneNotSupportedException, FileNotFoundException {
Person person = new Person();
person.setName("张三");
Pet pet = new Pet();
pet.setName("大黄");
person.setPet(pet);
try (ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("person.txt"))) {
outputStream.writeObject(person);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Data
public class Pet {
private String name;
}
java.io.NotSerializableException: com.example.hello.mianshi.Pet
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at com.example.hello.mianshi.Person.main(Person.java:23)
最好显示提供serialVersionUID
实现 Serializable 接口的类不显式地声明 serialVersionUID 字段时,Java 会自动生成一个 serialVersionUID,这种方式的缺点是它会基于类的结构自动生成一个 serialVersionUID,可能会因为类的修改而改变。当serialVersionUID不一致时就会报InvalidClassException异常
序列化时有name和age
@Data
public class Person implements Serializable {
private String name;
private int age;
public static void main(String[] args) throws CloneNotSupportedException, FileNotFoundException {
serialize();
}
private static void serialize() {
Person person = new Person();
person.setName("张三");
person.setAge(18);
try (ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("person.txt"))) {
outputStream.writeObject(person);
} catch (IOException e) {
e.printStackTrace();
}
}
}
反序列化时少了age,多了gender
@Data
public class Person implements Serializable {
private String name;
private String gender;
public static void main(String[] args) throws CloneNotSupportedException, FileNotFoundException {
deserialize();
}
private static void deserialize() {
try (ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("person.txt"))) {
Object o = inputStream.readObject();
System.out.println("o = " + o);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
报错
java.io.InvalidClassException: com.example.hello.mianshi.Person; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 1518472723010370216
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
加上serialVersionUID
@Data
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public static void main(String[] args) throws CloneNotSupportedException, FileNotFoundException {
serialize();
}
private static void serialize() {
Person person = new Person();
person.setName("张三");
person.setAge(18);
try (ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("person.txt"))) {
outputStream.writeObject(person);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Data
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String gender;
public static void main(String[] args) throws CloneNotSupportedException, FileNotFoundException {
deserialize();
}
private static void deserialize() {
try (ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("person.txt"))) {
Object o = inputStream.readObject();
System.out.println("o = " + o);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
o = Person(name=张三, gender=null)
可序列化类的所有子类型本身都是可序列化的。因为实现接口也是间接的等同于继承。
利用fastjson等工具时,不实现Serializable不会报错,