java eclipse O que é um serialVersionUID e por que devo usá-lo?



10 Answers

Se você está serializando apenas porque você tem que serializar para o bem da implementação (quem se importa se você serializar para uma sessão HTTPS, por exemplo ... se ela é armazenada ou não, você provavelmente não se importa em desserializar um objeto de formulário) então você pode ignorar isso.

Se você estiver realmente usando serialização, só importa se você planeja armazenar e recuperar objetos usando serialização diretamente. O serialVersionUID representa sua versão de classe e você deve incrementá-lo se a versão atual de sua classe não for compatível com versões anteriores.

Na maioria das vezes, você provavelmente não usará a serialização diretamente. Se esse for o caso, gere um uid serializável padrão clicando na opção de correção rápida e não se preocupe com isso.

java how to generate serialversionuid

O Eclipse emite avisos quando um serialVersionUID está ausente.

A classe serializável Foo não declara um campo serialVersionUID final estático do tipo longo

O que é serialVersionUID e por que é importante? Por favor, mostre um exemplo onde faltando serialVersionUID irá causar um problema.




Você pode dizer ao Eclipse para ignorar esses avisos serialVersionUID:

Janela> Preferências> Java> Compilador> Erros / Avisos> Problemas potenciais de programação

Caso você não saiba, há muitos outros avisos que você pode habilitar nesta seção (ou até mesmo alguns relataram como erros), muitos são muito úteis:

  • Problemas potenciais de programação: Possível atribuição booleana acidental
  • Problemas potenciais de programação: acesso a ponteiro nulo
  • Código desnecessário: a variável local nunca é lida
  • Código desnecessário: verificação nula redundante
  • Código desnecessário: elenco desnecessário ou 'instanceof'

e muitos mais.




O que é um serialVersionUID e por que devo usá-lo?

SerialVersionUID é um identificador exclusivo para cada classe, a JVM usa-o para comparar as versões da classe assegurando que a mesma classe foi usada durante a Serialização é carregada durante a Desserialização.

Especificar um fornece mais controle, embora a JVM gere um, se você não especificar. O valor gerado pode diferir entre diferentes compiladores. Além disso, às vezes você só quer, por algum motivo, proibir a desserialização de objetos serializados antigos [ backward incompatibility ] e, nesse caso, você só precisa alterar o serialVersionUID.

Os javadocs para Serializable dizem :

a computação serialVersionUID padrão é altamente sensível a detalhes de classe que podem variar dependendo das implementações do compilador e, portanto, podem resultar em InvalidClassException s inesperadas durante a desserialização.

Portanto, você deve declarar serialVersionUID porque nos dá mais controle .

Este artigo tem alguns pontos positivos sobre o assunto.




Se você receber este aviso em uma classe que você nunca pensou em serializar, e que você não se declarou implements Serializable , é muitas vezes porque você herdou de uma superclasse, que implementa Serializable. Muitas vezes, então, seria melhor delegar a esse objeto em vez de usar herança.

Então, ao invés de

public class MyExample extends ArrayList<String> {

    public MyExample() {
        super();
    }
    ...
}

Faz

public class MyExample {
    private List<String> myList;

    public MyExample() {
         this.myList = new ArrayList<String>();
    }
    ...
}

e nos métodos relevantes, chame myList.foo() vez de this.foo() (ou super.foo() ). (Isso não se encaixa em todos os casos, mas ainda com bastante frequência.)

Muitas vezes vejo pessoas estendendo o JFrame ou algo parecido, quando elas realmente precisam delegar isso. (Isso também ajuda na conclusão automática em um IDE, já que o JFrame tem centenas de métodos, que você não precisa quando quer chamar os personalizados na sua classe.)

Um caso em que o aviso (ou o serialVersionUID) é inevitável é quando você estende de AbstractAction, normalmente em uma classe anônima, apenas adicionando o método actionPerformed. Eu acho que não deve haver um aviso nesse caso (já que você normalmente não pode serializar e desserializar essas classes anônimas de qualquer maneira em diferentes versões de sua classe), mas não tenho certeza de como o compilador poderia reconhecer isso.




Para entender o significado do campo serialVersionUID, deve-se entender como funciona a serialização / desserialização.

Quando um objeto de classe Serializable é serializado, o Java Runtime associa um número de versão serial (chamado como serialVersionUID) a esse objeto serializado. No momento em que você desserializa esse objeto serializado, o Java Runtime corresponde ao serialVersionUID do objeto serializado com o serialVersionUID da classe. Se ambos forem iguais, então somente o processo posterior de desserialização será lançado InvalidClassException.

Assim, concluímos que, para que o processo de serialização / desserialização seja bem-sucedido, o serialVersionUID do objeto serializado deve ser equivalente ao serialVersionUID da classe. Caso o programador especifique o valor serialVersionUID explicitamente no programa, o mesmo valor será associado ao objeto serializado e à classe, independentemente da plataforma de serialização e desserialização (por exemplo, a serialização pode ser feita em plataformas como janelas usando sun ou MS JVM e Deserialization podem estar em diferentes plataformas Linux usando Zing JVM).

Mas, no caso de se serialVersionUID não ser especificado pelo programador, ao executar Serialization \ DeSerialization de qualquer objeto, o Java Runtime usa seu próprio algoritmo para calculá-lo. Este algoritmo de cálculo serialVersionUID varia de um JRE para outro. Também é possível que o ambiente em que o objeto é serializado esteja usando um JRE (ex: SUN JVM) e o ambiente no qual ocorre a deserialização esteja usando o Linux Jvm (zing). Nesses casos, serialVersionUID associado ao objeto serializado será diferente do serialVersionUID da classe calculada no ambiente de deserialização. Por sua vez, a desserialização não será bem-sucedida. Portanto, para evitar tais situações / problemas, o programador deve sempre especificar serialVersionUID da classe Serializable.




Quanto a um exemplo em que o serialVersionUID ausente pode causar um problema:

Eu estou trabalhando neste aplicativo Java EE que é composto de um módulo da Web que usa um módulo EJB . O módulo da web chama o módulo EJB remotamente e passa um POJO que implementa Serializable como um argumento.

POJO's classe deste POJO's foi empacotada dentro do jar do EJB e dentro de seu próprio jar no WEB-INF / lib do módulo web. Eles são na verdade a mesma classe, mas quando eu empacotei o módulo EJB eu descompactei o jar do POJO para empacotá-lo junto com o módulo EJB.

A chamada para o EJB estava falhando com a exceção abaixo porque eu não tinha declarado seu serialVersionUID :

Caused by: java.io.IOException: Mismatched serialization UIDs : Source
 (Rep.
 IDRMI:com.hordine.pedra.softbudget.domain.Budget:5CF7CE11E6810A36:04A3FEBED5DA4588)
 = 04A3FEBED5DA4588 whereas Target (Rep. ID RMI:com.hordine.pedra.softbudget.domain.Budget:7AF5ED7A7CFDFF31:6227F23FA74A9A52)
 = 6227F23FA74A9A52



Dados de campo representam algumas informações armazenadas na classe. Classe implementa a interface Serializable , então o eclipse ofereceu automaticamente para declarar o campo serialVersionUID . Vamos começar com o valor 1 definido lá.

Se você não quiser que o aviso venha, use isto:

@SuppressWarnings("serial")



Seria bom se CheckStyle pudesse verificar que o serialVersionUID em uma classe que implementa Serializable tem um bom valor, ou seja, que ele corresponde ao que o gerador de ID de versão serial produziria. Se você tem um projeto com muitos DTOs serializáveis, por exemplo, lembrar de excluir o serialVersionUID existente e regenerá-lo é uma dor, e atualmente a única maneira (que eu sei) de verificar isso é regenerar para cada classe e comparar com o antigo. Isso é muito doloroso.




Por que usar SerialVersionUIDdentro da Serializableclasse em Java?

Durante serialization, o Java runtime cria um número de versão para uma classe, para que possa desserializá-lo posteriormente. Este número de versão é conhecido como SerialVersionUIDem Java.

SerialVersionUIDé usado para dados serializados de versão. Você só pode desserializar uma classe se ela SerialVersionUIDcorresponder à instância serializada. Quando não declaramos SerialVersionUIDem nossa classe, o Java runtime gera para nós, mas não é recomendado. É recomendado declarar SerialVersionUIDcomo private static final longvariável para evitar o mecanismo padrão.

Quando você declara uma classe como Serializableimplementando a interface do marcador java.io.Serializable, o tempo de execução Java mantém a instância dessa classe no disco usando o mecanismo de serialização padrão, desde que você não tenha personalizado o processo usando a Externalizableinterface.

veja também Por que usar SerialVersionUID dentro da classe Serializable em Java

Código: javassist.SerialVersionUID




Esta questão está muito bem documentada em Java efetivo por Joshua Bloch. Um livro muito bom e uma leitura obrigatória. Vou descrever algumas das razões abaixo:

O tempo de execução de serialização vem com um número chamado versão serial para cada classe serializável. Esse número é chamado serialVersionUID. Agora existe algum Math por trás deste número e ele é baseado nos campos / métodos que são definidos na classe. Para a mesma classe, a mesma versão é gerada todas as vezes. Esse número é usado durante a desserialização para verificar se o remetente e o destinatário de um objeto serializado carregaram classes para esse objeto que são compatíveis com relação à serialização. Se o receptor tiver carregado uma classe para o objeto que tenha um serialVersionUID diferente daquele da classe do remetente correspondente, a desserialização resultará em um InvalidClassException.

Se a classe for serializável, você também pode declarar seu próprio serialVersionUID explicitamente declarando um campo chamado "serialVersionUID" que deve ser estático, final e do tipo long. A maioria dos IDE, como o Eclipse, ajuda você a gerar essa longa cadeia.




Related