2012-01-03 2 views
0

Почему конструктор класса Food and Fruit называется, когда я deserialize, где конструктор SkinFruit и Banana2 не вызывается в приведенном ниже примере?Если сериализация наследуется в иерархии, тогда будет вызываться конструктор класса, не реализующий сериализуемый. Почему это так?

Пусть я следующие иерархии классов

class Food{ 
    public Food() { System.out.println("1"); } 
    } 

class Fruit extends Food { 
    public Fruit() { System.out.print("2"); } 
} 

class SkinFruit extends Fruit implements Serializable{ 
    SkinFruit() { System.out.print("3"); } 
} 
public class Banana2 extends SkinFruit { 
    private static final long serialVersionUID = 1L; 
    int size = 42; 

    public static void main(String [] args) { 
     Banana2 b = new Banana2(); 
     FileOutputStream fost; 
     try { 
      fost = new FileOutputStream(new File("d:/testbanana.ser")); 
      ObjectOutputStream oostr= new ObjectOutputStream(fost); 
      oostr.writeObject(b); 
      oostr.flush();   
      oostr.close(); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     }catch (IOException e) { 
      e.printStackTrace(); 
     } 

     try { 
      FileInputStream fin= new FileInputStream(new File("d:/testbanana.ser")); 
      ObjectInputStream objin= new ObjectInputStream(fin); 
      b=(Banana2)objin.readObject(); 

     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
     } 


     System.out.println(" restored "+ b.size + ""); 
    } 
} 
+0

Вы уверены, что ваши объекты сериализуются в классе A? Не могли бы вы разместить код сериализации и десериализации? –

+0

Не вводите код из памяти в свой вопрос. Всегда копировать и вставлять. –

+0

, который из вашего класса реализует Serializable интерфейс? –

ответ

2

Ни называется, потому что ваш класс не Serializable.

Вы не можете назвать B() без вызова A() потому, что B называет A.

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

public static void main(String... args) throws Exception { 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    ObjectOutputStream oos = new ObjectOutputStream(baos); 
    oos.writeObject(new B()); 
    oos.writeObject(new D()); 
    oos.close(); 
    System.out.println("-------------"); 
    ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); 
    System.out.println("deserialize B"); 
    ois.readObject(); 
    System.out.println("deserialize D"); 
    ois.readObject(); 
} 

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

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

static class C implements Serializable { 
    public C() { 
     System.out.println("Inside class C"); 
    } 
} 

static class D extends C { 
    public D() { 
     System.out.println("Inside class D"); 
    } 
} 

отпечатки

Inside class A 
Inside class B 
Inside class C 
Inside class D 
------------- 
deserialize B 
Inside class A 
deserialize D 

А является не Сериализуемый родителем В. не сериализуется, и поэтому конструктор должен вызываться для установки любых полей, которые необходимо установить. Тем не менее, B, C и D являются Serializable и их поля являются сериализуемыми и будут сброшены. Нет необходимости вызывать конструктор.

+0

Хороший ответ ... но внутренне как объект B, C или D, созданный в куче. Используется ли отражение, например Class.newInstance() или Constructor.newInstance()? – Jyotirup

5

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

Если вызван конструктор класса A, это потому, что сам класс A не реализует Serializable. Во время десериализации называется беззаметным конструктором первого несериализуемого класса в иерархии наследования (возможно, java.lang.Object). Если этот класс не имеет конструктора без параметров, будет исключение.

0

Если вы хотите повторно создать некоторую информацию, когда объект десериализуется, вы должны использовать реализацию метода ниже в своем классе Serializable. Например, введите код ниже B.

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 
    System.out.println("Resurrecting B"); 
} 

Другие один для сериализации, только в случае, если вы хотите сделать некоторые вещи, прежде чем объект получает списан.

private void writeObject(ObjectOutputStream out) throws IOException { 
    // do stuff. 
} 
Смежные вопросы