Рубрики
Без рубрики

Java – Что такое serialVersionUID

– Ява – Что такое serialVersionUID

В Java serialVersionUID – это что-то вроде контроля версий, гарантирующего, что как сериализованные, так и десериализованные объекты используют совместимый класс.

Например, если объект сохранен в файл (сериализация) с serialVersionUID=1L , , когда мы преобразуем файл обратно в объект (сериализация), мы должны использовать тот же serialVersionUID=1L , в противном случае создается исключение InvalidClassException

Exception in thread "main" java.io.InvalidClassException: com.mkyong.io.object.Address;

    local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2

1. ПОЖО

Просмотрите простой Адрес класс, реализует Сериализуемый и объявляет serialVersionUID .

package com.mkyong.io.object;

import java.io.Serializable;

public class Address implements Serializable {

    private static final long serialVersionUID = 1L;

    String street;
    String country;

    public Address(String street, String country) {
        this.street = street;
        this.country = country;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    @Override
    public String toString() {
        return "Address{" +
                "street='" + street + '\'' +
                ", country='" + country + '\'' +
                '}';
    }
}

2. Проверьте serialVersionUID.

2.1 Сохраните объект в файл и преобразуйте его обратно из файла в объект.

package com.mkyong.io.object;

import java.io.*;

public class ObjectUtils {

    public static void main(String[] args) throws IOException, ClassNotFoundException {

        Address address = new Address("abc", "Malaysia");

        // object -> file
        try (FileOutputStream fos = new FileOutputStream("address.obj");
             ObjectOutputStream oos = new ObjectOutputStream(fos)) {
            oos.writeObject(address);
            oos.flush();
        }

        Address result = null;
        // file -> object
        try (FileInputStream fis = new FileInputStream("address.obj");
             ObjectInputStream ois = new ObjectInputStream(fis)) {
            result = (Address) ois.readObject();
        }

        System.out.println(result);

    }

}

Выход

  Address{street='abc', country='Malaysia'}

2.2 Обновите serialVersionUID до 99L .

public class Address implements Serializable {

    private static final long serialVersionUID = 99L;

    String street;
    String country;
    //...

Повторите процесс десериализации.

  Address result = null;
  // file -> object
  try (FileInputStream fis = new FileInputStream("address.obj");
       ObjectInputStream ois = new ObjectInputStream(fis)) {
      result = (Address) ois.readObject();
  }

  System.out.println(result);

Теперь мы попали Исключение InvalidClassException .

Exception in thread "main" java.io.InvalidClassException: com.mkyong.io.object.Address;

  local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 99

  at java.base/java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:689)
  at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1903)
  at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1772)
  at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2060)
  at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1594)
  at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:430)

3. Когда я должен обновить идентификатор serialVersionUID?

Когда мы изменяем класс, который нарушит совместимость с существующим сериализованным объектом, например, мы обновляем текущий Адрес класс, с добавлением и удалением некоторых полей.

Это новое изменение приведет к сбою всех существующих сериализованных объектов, затем мы должны обновить serialVersionUID .

public class Address implements Serializable {

    private static final long serialVersionUID = 9999L;

    String line1;
    String line2;
    Country country;

    //String street;
    //String country;
}

4. Идентификатор серийной версии по умолчанию?

Если serialVersionUID не объявлен, JVM будет использовать свой алгоритм для создания serialVersionUID по умолчанию , проверьте алгоритм здесь . Вычисление по умолчанию serialVersionUID очень чувствительно к деталям класса и может отличаться в разных реализациях JVM и приводить к неожиданному Исключения InvalidClassExceptions во время процесса десериализации.

Рассмотрим следующий пример:

Среда Клиент/сервер – Клиент использует OpenJDK в Windows. – Сервер использует GraalVM В Linux.

Клиент отправляет сериализованный класс с serialVersionUID=1L на сервер. Сервер может десериализовать класс с другим serialVersionUID=99L и выбрасывает Исключение Invalidclassexception . Поскольку оба используют разные реализации JVM, на обоих сайтах может быть создан другой serialVersionUID .

Существует множество реализаций JVM

Скачать Исходный Код

$клон git https://github.com/mkyong/core-java.git

$cd java-ввод-вывод

Рекомендации

Оригинал: “https://mkyong.com/java-best-practices/understand-the-serialversionuid/”