Интервьюер: Почему сериализация Java реализует интерфейс Serializable? я ошеломлен

Java

Я разобрал кое-какую архитектуру Java и материалы интервью (микросервисы, кластеры, распределенное, промежуточное ПО и т.д.), а друзья, кому нужно, могут обратить внимание на официальный аккаунт [Внутренние дела программиста], и получить самостоятельно без всяких рутин

более предпочтительно

написать впереди

Недавно фанат официального аккаунта болтал со мной о своем опыте собеседования. Новичок, который только что вошел в Java два года назад, из-за эпидемии проходит видеоинтервью, и интервьюер задал всего один вопрос: "JavaПочему реализована сериализация?Serializableинтерфейс? », и в результате он растерялся для интервьюOVER. Честно говоря, я был немного смущен, когда услышал этот вопрос, обычно я был занят изучением различных промежуточных программ и фреймворков высокой доступности.JavaСерийные знания.

Что такое Java-сериализация?

Сериализация:JavaМеханизм сериализации может записывать информацию об объекте экземпляра в поток байтов (Сериализуйте только значения свойств объекта, а не десериализуйте методы.), сериализованный объект можно использовать для передачи по сети или сохранять в базе данных или на диске.

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

JavaЧтобы сделать класс сериализуемым, реализуйтеjava.io.SerializableИнтерфейс самый простой.

public class User implements Serializable {

    private static final long serialVersionUID = 1L;
}

Итак, давайте посмотримSerializableИсходный код реализации интерфейса вы можете посмотретьSerializableВ интерфейсе нет методов или полей.Этот интерфейс используется только для определения сериализуемой семантики, то есть он используется только для определения возможности сериализации объекта.

package java.io;

/**
 * @author  unascribed
 * @see java.io.ObjectOutputStream
 * @see java.io.ObjectInputStream
 * @see java.io.ObjectOutput
 * @see java.io.ObjectInput
 * @see java.io.Externalizable
 * @since   JDK1.1
 */
public interface Serializable {
}

Далее напишем пример записи информации об объекте на диск для проверки:

СоздаватьUserобъект и реализоватьSerializableинтерфейс

@Data
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    private String name;

    private String age;
}

будетUserИнформация об объекте записывается на диск

@Slf4j
public class serializeTest {
    
    public static void main(String[] args) throws Exception {
        User user = new User();
        user.setName("fufu");
        user.setAge("18");

        serialize(user);
        log.info("Java序列化前的结果:{} ", user);

        User duser = deserialize();
        log.info("Java反序列化的结果:{} ", duser);
    }
    /**
     * @author xzf
     * @description 序列化
     * @date 2020/2/22 19:34
     */
    private static void serialize(User user) throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("D:\\111.txt")));
        oos.writeObject(user);
        oos.close();
    }
    /**
     * @author xzf
     * @description 反序列化
     * @date 2020/2/22 19:34
     */
    private static User deserialize() throws Exception {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("D:\\111.txt")));
        return (User) ois.readObject();
    }
}

序列化前的结果: User(name=fufu, age=18)
反序列化后的结果: User(name=fufu, age=18)

ОткрытымwriteObjectПосмотрите исходный код метода и обнаружите, что в методе есть такая логика, когда записываемый объектString,Array,Enum,SerializableОбъекты типа могут быть сериализованы нормально, в противном случае он выдастNotSerializableExceptionаномальный.

Это объясняет, почему должна быть реализована сериализация Java.Serializableинтерфейс.

/**
     * Underlying writeObject/writeUnshared implementation.
     */
    private void writeObject0(Object obj, boolean unshared)
        throws IOException
    {
        boolean oldMode = bout.setBlockDataMode(false);
        depth++;
        try {
            // 省略号。。。。。。。。。。

            // remaining cases
            if (obj instanceof String) {
                writeString((String) obj, unshared);
            } else if (cl.isArray()) {
                writeArray(obj, desc, unshared);
            } else if (obj instanceof Enum) {
                writeEnum((Enum<?>) obj, desc, unshared);
            } else if (obj instanceof Serializable) {
                writeOrdinaryObject(obj, desc, unshared);
            } else {
                if (extendedDebugInfo) {
                    throw new NotSerializableException(
                        cl.getName() + "\n" + debugInfoStack.toString());
                } else {
                    throw new NotSerializableException(cl.getName());
                }
            }
        } finally {
            depth--;
            bout.setBlockDataMode(oldMode);
        }
    }

Тогда могут быть сомнения,StringПочему бы не реализоватьSerializableЧто насчет интерфейса? фактическиStringбыл реализован внутриSerializable, без повторного показа реализации. Просто посмотрите исходный код

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -6849794470754667710L;

    ......
}

С тех пор, как это было реализованоSerializableинтерфейс, почему вы хотите указатьserialVersionUIDзначение ?

Потому что при сериализации объекта, если настройка не отображаетсяserialVersionUID, Java автоматически сгенерируетserialVersionUID, а затем сохраните его или используйте для передачи по сети.

При десериализации он автоматически сгенерирует новый на основе свойств объекта.serialVersionUID, и генерируется при сериализацииserialVersionUIDдля сравнения, дваserialVersionUIDЕсли то же самое, десериализация прошла успешно, иначе будет выброшено исключение.

И когда отображаемые настройкиserialVersionUIDПосле этого, когда Java сериализует и десериализует объекты, сгенерированныйserialVersionUIDвсе готово для насserialVersionUID, что обеспечивает успех десериализации.

transient

При сериализации объекта, если вы хотите, чтобы свойство не сериализовалось, используйтеtransientизменение ключевого слова

@Data
public class User implements Serializable {

    private transient String name;

    private String age;
}

могут видеть поляnameЗначение не сохраняется на диск после того, как переменнаяtransientИзмененная переменная больше не будет частью постоянства объекта, и доступ к содержимому переменной после сериализации будет невозможен.

Java序列化前的结果: User(name=fufu, age=18)
Java反序列化的结果:User(name=null, age=18)

Статическая переменная независимо от того, является ли онаtransientМодификации не могут быть сериализованы. так какstaticДекорированные свойства принадлежат классу, а не объекту.

Суммировать

Поделился небольшим знанием, не забывайте об этом, как бы вы ни были занятыУчитесь у прошлого!

Так много, что нужно сказать сегодня, если эта статья была вам полезна, я надеюсь получить от вас лайк 👍

Ваше одобрение является движущей силой для моего письма!

Я разобрал кое-какую архитектуру Java и материалы интервью (микросервисы, кластеры, распределенное, промежуточное ПО и т.д.), а друзья, кому нужно, могут обратить внимание на официальный аккаунт [Внутренние дела программиста], и получить самостоятельно без всяких рутин