Pergunta

Eu tenho:

class MyClass extends MyClass2 implements Serializable {
  //...
}

Em MinhaClasse2 é uma propriedade que não é serializável. Como posso serializar (e de-serialize) este objeto?

Correção: MinhaClasse2 é, naturalmente, não uma interface, mas uma classe

.
Foi útil?

Solução

Como alguém observou, capítulo 11 do Java eficaz de Josh Bloch é um recurso indispensável em Java serialização.

pontos casal Um dos que pertinente capítulo à sua pergunta:

  • supondo que você quer serializar o estado do campo não serializável em MinhaClasse2, esse campo deve ser acessível a MyClass, diretamente ou através de getters e setters. MyClass terá que implementar serialização personalizada, fornecendo métodos readObject e writeObject.
  • Classe do campo não serializável deve ter uma API para permitir que começá-lo do estado (para gravar o fluxo de objeto) e, em seguida, instanciar uma nova instância com aquele estado (quando mais tarde leitura do fluxo de objeto.)
  • per item 74 do Effective Java, MinhaClasse2 deve ter um construtor no-arg acessível a MyClass, caso contrário é impossível para MyClass para estender MinhaClasse2 e implementar Serializable.

Eu escrevi um exemplo rápido abaixo ilustra isso.


class MyClass extends MyClass2 implements Serializable{

  public MyClass(int quantity) {
    setNonSerializableProperty(new NonSerializableClass(quantity));
  }

  private void writeObject(java.io.ObjectOutputStream out)
  throws IOException{
    // note, here we don't need out.defaultWriteObject(); because
    // MyClass has no other state to serialize
    out.writeInt(super.getNonSerializableProperty().getQuantity());
  }

  private void readObject(java.io.ObjectInputStream in)
  throws IOException {
    // note, here we don't need in.defaultReadObject();
    // because MyClass has no other state to deserialize
    super.setNonSerializableProperty(new NonSerializableClass(in.readInt()));
  }
}

/* this class must have no-arg constructor accessible to MyClass */
class MyClass2 {

  /* this property must be gettable/settable by MyClass.  It cannot be final, therefore. */
  private NonSerializableClass nonSerializableProperty;

  public void setNonSerializableProperty(NonSerializableClass nonSerializableProperty) {
    this.nonSerializableProperty = nonSerializableProperty;
  }

  public NonSerializableClass getNonSerializableProperty() {
    return nonSerializableProperty;
  }
}

class NonSerializableClass{

  private final int quantity;

  public NonSerializableClass(int quantity){
    this.quantity = quantity;
  }

  public int getQuantity() {
    return quantity;
  }
}

Outras dicas

MinhaClasse2 é apenas uma interface tão techinicaly que não tem propriedades, apenas métodos. Dito isto, se você tem variáveis ??de instância que são eles próprios não serializeable a única maneira que eu conheço para contorná-la é declarar os campos transitórios.

ex:

private transient Foo foo;

Quando você declarar um transiente campo será ignorado durante o processo de serialização e desserialização. Tenha em mente que quando você desserializar um objeto com um campo transiente que o valor do campo será sempre a sua padrão (geralmente nulo.)

Note que você também pode substituir o método readResolve () de sua classe, a fim de inicializar campos transitórios baseado em outro estado do sistema.

Se possível, as partes não serialiable pode ser definido como transitória

private transient SomeClass myClz;

Caso contrário, você pode usar Kryo . Kryo é um rápido e eficiente de serialização quadro gráfico objecto para Java (por exemplo JAVA serialização de java.awt.Color requer 170 bytes, Kryo apenas 4 bytes), que pode serializar também objectos não serializados. Kryo também pode executar profunda automática e superficial copiar / clonagem. Esta é a cópia direta do objeto a objeto, não object->bytes->object.

Aqui está um exemplo de como usar KRYO

Kryo kryo = new Kryo();
// #### Store to disk...
Output output = new Output(new FileOutputStream("file.bin"));
SomeClass someObject = ...
kryo.writeObject(output, someObject);
output.close();
// ### Restore from disk...
Input input = new Input(new FileInputStream("file.bin"));
SomeClass someObject = kryo.readObject(input, SomeClass.class);
input.close();

objetos serializados pode também ser comprimido por registrar serializer exata:

kryo.register(SomeObject.class, new DeflateCompressor(new FieldSerializer(kryo, SomeObject.class)));

Se você pode modificar MinhaClasse2, a maneira mais fácil de resolver isso é declarar o transitório propriedade.

Você precisará implementar writeObject() e readObject() e fazer manual de serialização / desserialização desses campos. Veja a página de javadoc para java.io.Serializable para mais detalhes. Josh Bloch do Effective Java também tem alguns bons capítulos sobre a implementação de serialização robusto e seguro.

Depende por que esse membro da MinhaClasse2 não é serializável.

Se há alguma boa razão para que MinhaClasse2 não pode ser representado em uma forma serializada, então as chances são boas pela mesma razão se aplica a MyClass, já que é uma subclasse.

Pode ser possível escrever um formulário serializado personalizado para MyClass através da implementação de readObject e writeObject, de maneira tal que o estado dos dados de instância MinhaClasse2 em MyClass podem ser adequadamente recriado a partir dos dados serializados. Este seria o caminho a percorrer se API do MinhaClasse2 é fixo e você não pode adicionar Serializable.

Mas primeiro você deve descobrir por que MinhaClasse2 não é serializável, e talvez mudá-lo.

Você pode começar por olhar para o transitória palavra-chave, que marca campos como não faz parte do estado persistente de um objeto.

Várias possibilidades poped fora e eu retomá-las aqui:

XStream é uma grande biblioteca para fazer rápido Java para serialização XML para qualquer objeto, não importa se é Serializable ou não. Mesmo se o formato de destino XML não combina com você, você pode usar o código-fonte para aprender a fazê-lo.

Uma abordagem útil para serializadas exemplos de classes não seriáveis ??(ou pelo menos as subclasses de) é conhecida uma série de proxy. Essencialmente, você implementar writeReplace para retornar uma instância de uma classe serializável completamente diferente que implementa readResolve para retornar uma cópia do objeto original. Eu escrevi um exemplo de serializadas java.awt.BasicStroke em Usenet

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top