Когда я запускаю данный код, я получаю ABA в качестве вывода. Я не понимаю, почему он снова печатает A

Упомянутый ниже код возвращает A B A в качестве вывода, но я не понял логики, почему A снова печатается после B.

class A1 {
    public A1() {
        System.out.println("A");
    }
}

class B extends A1 implements Serializable {
    public B() {
        System.out.println("B");
    }

}

public class Test {

    public static void main(String... args) throws Exception {
        B b = new B();      // Object of class B
        ObjectOutputStream objout=new ObjectOutputStream(new FileOutputStream("t.txt"));
        objout.writeObject(b);

        ObjectInputStream objin=new ObjectInputStream(new FileInputStream("t.txt"));
        objin.readObject();
    }

}

person yuvraj    schedule 28.09.2013    source источник
comment
Проверьте эту ссылку stackoverflow.com/questions/12317063/   -  person Deepak Kumar Jha    schedule 28.09.2013


Ответы (5)


Это объясняет, что ctor B больше не вызывается, потому что он сериализуем.

Чтение объекта аналогично запуску конструкторов нового объекта. Память выделяется для объекта и инициализируется нулем (NULL). Для несериализуемых классов вызываются конструкторы без аргументов.

A B печатается, когда вы вызываете new B(), который сначала вызывает ctor A, а затем B. Затем objin.readObject() вызывает только ctor A и печатает второй A.

person Eran    schedule 28.09.2013
comment
Спасибо!. Я проверил и понял логику. - person yuvraj; 28.09.2013

Конструктор для A вызывается во время десериализации, поскольку A не реализует Serializable. Этот ответ хорошо объясняет это:

Java: почему десериализация не вызывает конструктор и что лучший обходной путь?

person Drew MacInnis    schedule 28.09.2013

Когда вы расширяете любой класс, он вызывает конструктор super class при создании объекта subclass.

Просто пример: object B создан, тогда он сначала вызовет конструктор A1. и objin.readObject() вызывает только конструктор A.

Изменить:

Конструктор без аргументов каждого несериализуемого суперкласса будет запускаться при десериализации объекта. Однако десериализованные объекты? конструктор не запускается при десериализации.

person bNd    schedule 28.09.2013
comment
не отвечает на вопрос - person upog; 28.09.2013
comment
@upog Да, это был не ответ, как ожидал OP. Я отредактировал ответ. Это может помочь ОП. - person bNd; 28.09.2013

Конструкторы вызываются из базового класса в производные классы.

Таким образом, для B b = new B(); конструкторы будут вызываться в порядке A->B. Следовательно, печать A B


Теперь для objin.readObject();

Будет вызываться только конструктор A, а не конструктор B. Это потому, что

  • Для сериализуемых объектов запускается конструктор без аргументов для первого несериализуемого супертипа (то есть A1). Поскольку A1 не реализует Serializable, будет вызван его конструктор

  • Конструкторы не выполняются для serializable классов (т.е. B) во время десериализации. Следовательно, конструктор B не вызывается во второй раз

Отсюда вывод, A B A

Это упоминается в doc.

person Anirudha    schedule 28.09.2013

В документации по Java ObjectInputStream говорится:

Чтение объекта аналогично запуску конструкторов нового объекта. Память выделяется для объекта и инициализируется нулем (NULL). Для несериализуемых классов вызываются конструкторы без аргументов, а затем поля сериализуемых классов восстанавливаются из потока, начиная с сериализуемого класса, ближайшего к java.lang.object, и заканчивая наиболее конкретный класс.

Поэтому при создании экземпляра класса B

B b = new B();  // prints A B

он печатает A, B и

при десериализации,

objin.readObject();  // prints A as per docs

он печатает A, потому что класс A не является сериализуемым, а в документах говорится, что конструкторы без аргументов вызываются для несериализуемых классов.

Итак, вместе вы получаете вывод как A B A

person Prateek    schedule 28.09.2013