Pergunta

Em Java, a estática e a transitória campos não são serializados.No entanto, eu descobri que a inicialização de campos estáticos faz com que o gerado serialVersionUID ser alterado.Por exemplo, static int MYINT = 3; faz com que o serialVersionUID alterar.Neste exemplo, não faz sentido porque as diferentes versões da classe de obter diferentes valores iniciais.Por que não faz qualquer inicialização alterar o serialVersionUID?Por exemplo, static String MYSTRING = System.getProperty("foo"); também faz com que o serialVersionUID alterar.

Para ser mais específico, a minha pergunta é por que a inicialização com um método de causar o serialVersionUID alterar.O problema de eu bater é que eu adicionei um novo campo estático que foi inicializado com um sistema de valor de propriedade (getProperty).Essa mudança causou uma serialização exceção de uma chamada remota.

Foi útil?

Solução

Você pode encontrar algumas informações sobre isso no erro 4365406 e no algoritmo para computação serialVersionUID.Basicamente, ao alterar a inicialização do seu static membro System.getProperty(), o compilador apresenta um novo static a propriedade em sua classe de referência a System classe (presumo que o System classe foi previamente não referenciados na sua classe), e uma vez que esta propriedade introduzida pelo compilador não é privado, ele toma parte na serialVersionUID computação.

A moralidade:sempre uso explícito serialVersionUID, você vai economizar alguns ciclos de CPU e de algumas dores de cabeça :)

Outras dicas

Automático serialVersionUID é calculado com base nos membros de uma classe.Estes podem ser apresentados para uma classe de arquivo utilizando a ferramenta javap no Sun JDK.

No caso mencionado na questão, o membro que for adicionado/removido é o estático initialiser.Este aparece como ()V em arquivos de classe.O conteúdo do método pode ser desmontado usando javap -c.Você deve ser capaz de fazer o Sistema.getProperty("foo") a chamada e a atribuição de MYSTRING.No entanto uma atribuição com um literal de cadeia de caracteres (ou qualquer compilação constante de tempo, como definido pela Especificação da Linguagem Java) é suportada diretamente pelo arquivo de classe, assim eliminando a necessidade de uma estático initialiser.

Um caso comum para o código de segmentação J2SE 1.4 (use -source 1.4 -alvo 1.4) ou anterior é estáticos campos velho instâncias de classes que aparecem como classe literais em código-fonte (MyClass.class).A instância da Classe é procurado demanda com Classe.forName, e armazenado em um campo estático.É este campo estático que interrompe o serialVersionUID.A partir do J2SE 5.0, uma variante da ldc opcode dá suporte direto para a classe de caracteres literais, eliminando a necessidade de o sintético do campo.Novamente, tudo isso pode ser mostrado com o javap -c.

Se eu ler a especificação corretamente automática serialVersionUID não deve mudar se você alterar o valor de um estático de transiente de campo.Dê uma olhada no Capítulo 5.6 da Especificação.

No entanto, se você pensar sobre isso um pouco - você comece por serializar um objeto que tem static int MYINT = 3, quando você, em seguida, anular a classe que você espera obter o mesmo objeto, isto é, com MYINT = 3.Então, se você alterar a inicialização estática seria de esperar que os serialVersionUID para mudar, porque você não pode obter o mesmo objecto de volta novamente.

De qualquer maneira, manter isso em todas as suas classes serializáveis e você pode controlar o serialVersionUID:

private static final long serialVersionUID = 7526472295622776147L;

Eu atualizei a questão para ser mais claro.Eu entendo o porquê de inicialização com um literal altera o serialVersionUID mas não é por isso inicialização dinâmica muda.Se você inicializar com um método, o valor, é claro, pode sempre ser diferente.

A definição do serialVersionUID explicitamente é bom em uma versão subseqüente da classe somente se tiver certeza de que é seguro alterar.

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