Quando a classe implementa Serializable no Eclipse, tenho duas opções: adicionar padrão serialVersionUID(1L)
ou gerado serialVersionUID(3567653491060394677L)
. Eu acho que o primeiro é mais legal, mas muitas vezes eu vi pessoas usando a segunda opção. Existe algum motivo para gerar long serialVersionUID
?
210
0L
apenas inicialmente.Respostas:
Até onde eu sei, isso seria apenas para compatibilidade com versões anteriores. Isso só seria útil se você deixasse de usar um serialVersionUID antes e, em seguida, fizesse uma alteração que você sabe que deveria ser compatível, mas que causa interrupção na serialização.
Consulte a especificação de serialização do Java para obter mais detalhes.
fonte
O objetivo da versão UID da serialização é acompanhar as diferentes versões de uma classe para executar a serialização válida dos objetos.
A idéia é gerar um ID exclusivo para uma determinada versão de uma classe, que é alterada quando há novos detalhes adicionados à classe, como um novo campo, que afetaria a estrutura do objeto serializado.
Sempre usando o mesmo ID, como
1L
significa que, no futuro, se a definição da classe for alterada e causar alterações na estrutura do objeto serializado, haverá uma boa chance de surgirem problemas ao tentar desserializar um objeto.Se o ID for omitido, o Java calculará o ID para você com base nos campos do objeto, mas acredito que seja um processo caro, portanto, fornecer um manualmente melhorará o desempenho.
Aqui estão alguns links para artigos que discutem serialização e controle de versão de classes:
fonte
Note - It is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected serialVersionUID conflicts during deserialization, causing deserialization to fail.
O comentário acima foi retirado da Especificação de serialização de objetos Java versão 6.0O principal motivo para o gerado seria torná-lo compatível com uma versão existente da classe que já possui cópias persistentes.
fonte
O padrão "long" de
serialVersionUID
é o valor padrão, conforme definido pela Java Serialization Specification , calculado a partir do comportamento de serialização padrão.Portanto, se você adicionar o número da versão padrão, sua classe será (des) serializada mais rapidamente, desde que nada tenha sido alterado estruturalmente, mas você deverá tomar cuidado para que, se alterar a classe (adicionar / remover campos), também atualize o número de série.
Se você não precisar ser compatível com os fluxos de bits existentes, basta colocar
1L
lá e incrementar a versão conforme necessário quando algo mudar. Ou seja, quando a versão padrão de serialização da classe alterada seria diferente da versão padrão da classe antiga.fonte
Você absolutamente deve criar um serialVersionUID toda vez que definir uma classe que implementa
java.io.Serializable
. Caso contrário, um será criado automaticamente para você, mas isso é ruim. O serialVersionUID gerado automaticamente é baseado nas assinaturas de método da sua classe, portanto, se você mudar sua classe no futuro para adicionar um método (por exemplo), a desserialização das versões "antigas" da classe falhará. Aqui está o que pode acontecer:fonte
Se você não especificar um serialVersionUID, o Java cria um em tempo real. O serialVersionUID gerado é esse número. Se você alterar algo em sua classe que realmente não a torne incompatível com as versões serializadas anteriores, mas altere o hash, será necessário usar o serialVersionUID de número muito grande gerado (ou o número "esperado" da mensagem de erro) . Caso contrário, se você estiver acompanhando tudo sozinho, 0, 1, 2 ... é melhor.
fonte
Ao usar serialVersionUID (1L) em vez de gerar serialVersionUID (3567653491060394677L), você está dizendo algo.
Você está dizendo que está 100% confiante de que nenhum sistema que jamais toque nessa classe que tenha uma versão serializada incompatível dessa classe com um número de versão 1.
Se você pode pensar em alguma desculpa para o histórico de versão serializado ser desconhecido, pode ser difícil dizer com confiança. Durante sua vida, uma classe de sucesso será mantida por muitas pessoas, viverá em muitos projetos e residirá em muitos sistemas.
Você pode sofrer por isso. Ou você pode jogar na loteria na esperança de perder. Se você gerar a versão, terá uma pequena chance de as coisas darem errado. Se você assumir "Ei, eu aposto que ninguém usou 1 ainda", suas chances são maiores que pequenas. É precisamente porque todos pensamos que 0 e 1 são legais que você tem maiores chances de atingi-los.
-
Ao gerar serialVersionUID (3567653491060394677L), em vez de usar serialVersionUID (1L), você está dizendo algo.
Você está dizendo que as pessoas podem ter criado ou gerado manualmente outros números de versão ao longo do histórico desta classe e você não se importa porque Longs está enlouquecendo grandes números.
De qualquer maneira, a menos que você conheça perfeitamente o histórico dos números de versão usados ao serializar a classe em todo o universo de onde ela existe ou que sempre existirá, você está arriscando. Se você tiver tempo para garantir 100% de certeza de que 1 é AOK, faça isso. Se isso der muito trabalho, vá em frente e gere o número cegamente. É mais provável que você ganhe na loteria do que errar. Se isso acontecer, me avise e eu comprarei uma cerveja para você.
Com toda essa conversa sobre jogar na loteria, posso ter lhe dado a impressão de que serialVersionUID é gerado aleatoriamente. De fato, desde que o intervalo de números seja distribuído uniformemente por todo valor possível de um Long, isso seria bom. No entanto, é realmente feito desta maneira:
http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100
A única diferença é que você não precisa de uma fonte aleatória. Você está usando as alterações na própria classe para alterar o resultado. Mas, de acordo com o princípio do buraco de pombo, ainda há uma chance de que possa dar errado e ter uma colisão. É incrivelmente improvável. Boa sorte em tirar uma cerveja de mim.
No entanto, mesmo que a classe viva apenas em um sistema e em uma base de código, pensando que incrementar o número manualmente oferece zero chances de colisões, apenas significa que você não entende humanos. :)
fonte
Bem, serialVersionUID é uma exceção à regra de que "campos estáticos não são serializados". ObjectOutputStream grava sempre que o valor de serialVersionUID no fluxo de saída. O ObjectInputStream o lê novamente e, se o valor lido no fluxo não concordar com o valor serialVersionUID na versão atual da classe, ele lançará o InvalidClassException. Além disso, se não houver serialVersionUID oficialmente declarado na classe para ser serializado, o compilador o adicionará automaticamente com um valor gerado com base nos campos declarados na classe.
fonte
Porque em muitos casos, o ID padrão não é exclusivo. então criamos um ID para criar um conceito único.
fonte
Para adicionar à resposta do @David Schmitts, como regra geral, eu sempre usaria o 1L padrão fora da convenção. Eu só tive que voltar e alterar alguns deles algumas vezes, mas sabia disso quando fiz a alteração e atualizei o número padrão por um de cada vez.
Na minha empresa atual, eles exigem o número gerado automaticamente, então eu o uso por convenção, mas prefiro o padrão. Minha opinião é que, se não for uma convenção em que você trabalha, use o padrão, a menos que você pense que estará constantemente alterando a estrutura de suas classes serializadas por algum motivo.
fonte
O objetivo da versão UID da serialização é acompanhar as diferentes versões de uma classe para executar a serialização válida dos objetos.
A idéia é gerar um ID exclusivo para uma determinada versão de uma classe, que é alterada quando há novos detalhes adicionados à classe, como um novo campo, que afetaria a estrutura do objeto serializado.
Uma explicação simples:
Você está serializando dados?
Serialização é basicamente gravar dados da classe em um arquivo / fluxo / etc. A desserialização está lendo esses dados de volta para uma classe.
Você pretende entrar em produção?
Se você está apenas testando algo com dados falsos / sem importância, não se preocupe com isso (a menos que esteja testando serialização diretamente).
Esta é a primeira versão?
Nesse caso, defina serialVersionUID = 1L.
Esta é a segunda, terceira, etc. versão do prod?
Agora você precisa se preocupar com o serialVersionUID e deve analisá-lo em profundidade.
Basicamente, se você não atualizar a versão corretamente quando atualizar uma classe, precisará escrever / ler, receberá um erro ao tentar ler dados antigos.
fonte