Por que Java tem campos transitórios?

Por que Java tem campos transitórios ?

    A palavra-chave transient em Java é usada para indicar que um campo não deve ser serializado.

    Da especificação da linguagem Java, Java SE 7 Edition , Seção 8.3.1.3. Campos transient :

    Variáveis ​​podem ser marcadas como transient para indicar que elas não fazem parte do estado persistente de um object.

    Por exemplo, você pode ter campos que são derivados de outros campos e devem ser feitos apenas de forma programática, em vez de manter o estado persistente por meio de serialização.

    Aqui está uma class GalleryImage que contém uma imagem e uma miniatura derivada da imagem:

     class GalleryImage implements Serializable { private Image image; private transient Image thumbnailImage; private void generateThumbnail() { // Generate thumbnail. } private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { inputStream.defaultReadObject(); generateThumbnail(); } } 

    Neste exemplo, o thumbnailImage é uma imagem em miniatura que é gerada chamando o método generateThumbnail .

    O campo thumbnailImage é marcado como transient , portanto, somente a image original é serializada, em vez de persistir tanto a imagem original quanto a imagem em miniatura. Isso significa que menos armazenamento seria necessário para salvar o object serializado. (Claro, isso pode ou não ser desejável dependendo dos requisitos do sistema – isso é apenas um exemplo).

    No momento da desserialização, o método readObject é chamado para executar quaisquer operações necessárias para restaurar o estado do object de volta ao estado no qual a serialização ocorreu. Aqui, a miniatura precisa ser gerada, então o método readObject é substituído para que a miniatura seja gerada chamando o método generateThumbnail .

    Para obter informações adicionais, o artigo Descubra os segredos da API de serialização Java (que estava originalmente disponível na Sun Developer Network) possui uma seção que discute o uso e apresenta um cenário em que a palavra-chave transient é usada para evitar a serialização de determinados campos.

    Antes de compreender a palavra-chave transient , é preciso entender o conceito de serialização. Se o leitor souber sobre serialização, pule o primeiro ponto.

    O que é serialização?

    Serialização é o processo de tornar o estado do object persistente. Isso significa que o estado do object é convertido em um stream de bytes e armazenado em um arquivo. Da mesma forma, podemos usar a desserialização para recuperar o estado do object dos bytes. Esse é um dos conceitos importantes na programação Java, porque a serialização é usada principalmente na programação de rede. Os objects que precisam ser transmitidos pela rede precisam ser convertidos em bytes. Para esse propósito, cada class ou interface deve implementar a interface Serializable . É uma interface de marcador sem nenhum método.

    Agora, qual é a palavra-chave transient e sua finalidade?

    Por padrão, todas as variables ​​do object são convertidas em um estado persistente. Em alguns casos, você pode querer evitar a persistência de algumas variables, porque você não tem a necessidade de persistir essas variables. Então você pode declarar essas variables ​​como transient . Se a variável for declarada como transient , ela não será persistida. Esse é o objective principal da palavra-chave transient .

    Eu quero explicar os dois pontos acima com o seguinte exemplo:

     package javabeat.samples; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; class NameStore implements Serializable{ private String firstName; private transient String middleName; private String lastName; public NameStore (String fName, String mName, String lName){ this.firstName = fName; this.middleName = mName; this.lastName = lName; } public String toString(){ StringBuffer sb = new StringBuffer(40); sb.append("First Name : "); sb.append(this.firstName); sb.append("Middle Name : "); sb.append(this.middleName); sb.append("Last Name : "); sb.append(this.lastName); return sb.toString(); } } public class TransientExample{ public static void main(String args[]) throws Exception { NameStore nameStore = new NameStore("Steve", "Middle","Jobs"); ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("nameStore")); // writing to object o.writeObject(nameStore); o.close(); // reading from object ObjectInputStream in = new ObjectInputStream(new FileInputStream("nameStore")); NameStore nameStore1 = (NameStore)in.readObject(); System.out.println(nameStore1); } } 

    E a saída será a seguinte:

     First Name : Steve Middle Name : null Last Name : Jobs 

    O nome do meio é declarado como transient , portanto, ele não será armazenado no armazenamento persistente.

    Fonte

    Para permitir que você defina variables ​​que não deseja serializar.

    Em um object, você pode ter informações que não deseja serializar / persistir (talvez uma referência a um object pai de fábrica), ou talvez não faça sentido serializar. Marcá-las como ‘transitórias’ significa que o mecanismo de serialização ignorará esses campos.

    Minha pequena contribuição:

    O que é um campo transitório?
    Basicamente, qualquer campo modificado com a palavra-chave transient é um campo transitório.

    Por que os campos temporários são necessários em Java?
    A palavra-chave transient fornece a você algum controle sobre o processo de serialização e permite excluir algumas propriedades do object desse processo. O processo de serialização é usado para persistir objects Java, principalmente para que seus estados possam ser preservados enquanto são transferidos ou inativos. Às vezes, faz sentido não serializar certos atributos de um object.

    Quais campos você deve marcar como transitórios?
    Agora sabemos o objective dos campos transient palavras-chave e transientes, é importante saber quais campos marcam transitórios. Os campos estáticos também não são serializados, portanto, a palavra-chave correspondente também funcionará. Mas isso pode arruinar seu design de class; é aí que a palavra-chave transient vem para o resgate. Eu tento não permitir que os campos cujos valores podem ser derivados de outros sejam serializados, então eu os marquei como transitórios. Se você tiver um campo chamado interest cujo valor pode ser calculado a partir de outros campos ( principal , rate e time ), não há necessidade de serializá-lo.

    Outro bom exemplo é a contagem de palavras do artigo. Se você estiver salvando um artigo inteiro, não há necessidade de salvar a contagem de palavras, porque ele pode ser calculado quando o artigo é “desserializado”. Ou pense em madeireiros; Logger instâncias do Logger quase nunca precisam ser serializadas, para que possam se tornar transitórias.

    Uma variável transient é uma variável que pode não ser serializada.

    Um exemplo de quando isso pode ser útil que vem à mente é, variables ​​que fazem sentido apenas no contexto de uma instância de object específica e que se tornam inválidas depois de serializar e desserializar o object. Nesse caso, é útil que essas variables ​​se tornem null para que você possa reinicializá-las com dados úteis, quando necessário.

    transient é usado para indicar que um campo de class não precisa ser serializado. Provavelmente, o melhor exemplo é um campo Thread . Geralmente não há razão para serializar um Thread , pois seu estado é muito “específico do stream”.

    Sistemas de serialização diferentes do java nativo também podem usar este modificador. O Hibernate, por exemplo, não persistirá nos campos marcados com @Transient ou com o modificador transitório . Terracota também respeita este modificador.

    Eu acredito que o significado figurativo do modificador é “este campo é apenas para uso em memory. Não persista ou mova-o para fora desta VM em particular de qualquer forma. Seu não-portátil”. ou seja, você não pode confiar em seu valor em outro espaço de memory da VM. Muito parecido com volatile significa que você não pode confiar em certas semânticas de memory e thread.

    Porque nem todas as variables ​​são de natureza serializável

    Serialização é o processo de salvar estados de um object em um formato persistente (como stream de arquivos ou database) e, posteriormente, restaurá-los de volta do stream (desserialização). Em Java, um object de uma class é serializável se a class implementar a interface java.io.Serializable. Essa é uma interface de marcador que informa à JVM que a class é elegível para serialização.

     public class User implements Serializable { private static final long serialVersionUID = 1234L; private String username; private String email; private transient String password; private Date birthday; private int age; public User(String username, String email, String password, Date birthday, int age) { this.username = username; this.email = email; this.password = password; this.birthday = birthday; this.age = age; } public void printInfo() { System.out.println("username: " + username); System.out.println("email: " + email); System.out.println("password: " + password); System.out.println("birthday: " + birthday); System.out.println("age: " + age); } // getters and setters } 

    Existem três pontos importantes nessa class de modelo: ele deve implementar a interface Serializable. Caso contrário, obteremos uma java.io.NotSerializableException ao tentar serializar um object da class. Uma constante denominada serialVersionUID é declarada e atribuída a um valor longo:

     private static final long serialVersionUID = 1234L; 

    Essa é uma constante convencional que deve ser declarada quando uma class implementa a interface Serializable. O UID da versão serial garante fortemente a compatibilidade entre as versões serializadas e não serializadas de objects de uma class, porque o processo de serialização e desserialização pode acontecer em diferentes computadores e sistemas. Embora essa declaração seja opcional, é sempre recomendável declarar o serialVersionUID para uma class serializável.

    Observe que o campo da senha está marcado como transitório:

     private transient String password; 

    Porque não queremos armazenar a senha ao serializar o object. A regra é, quando uma variável é marcada como transiente, seu object não será serializado durante a serialização.

    Uma variável transitória é uma variável que pode não ser serializada. Você usa a palavra-chave temporária para indicar à máquina virtual Java que a variável indicada não faz parte do estado persistente do object.

    Os modificadores de access suportados pelo Java são estático, final, abstrato, sincronizado, nativo, volátil, transitório e strictfp.

    A tabela a seguir fornece a lista de especificadores de access e modificadores Java que podem ser aplicados a variables, methods e classs.

     SPECIFIER/MODIFIER LOCAL VARIABLE INSTANCEVARIABLE METHOD CLASS public NA AAA protected NA AA NA default AAAA private NA AA NA final AAAA static NA AA NA synchronized NA NA A NA native NA NA A NA volatile NA A NA NA transient NA A NA NA strictfp NA NA AA 

    Antes de responder a esta pergunta, devo explicar-lhe a SERIALIZAÇÃO , porque se você entende o que significa serialização no computador da ciência você pode facilmente entender esta palavra-chave.

    Serialização Quando um object é transferido através da rede / salvo em mídia física (arquivo, …), o object deve ser “serializado”. Serialização converte a série de objects de status de byte. Esses bytes são enviados na rede / salvos e o object é recriado a partir desses bytes.
    Exemplo

     public class Foo implements Serializable { private String attr1; private String attr2; ... } 

    Agora, se você quer fazer não transferir / salvar campo deste object SO , você pode usar a palavra-chave transient

     private transient attr2; 

    Exemplo

    É necessário quando você não quer compartilhar alguns dados confidenciais que acompanham a serialização.

    de acordo com o significado transitório do google == duração apenas por um curto período de tempo; impermanente.

    Agora, se quiser fazer algo transitório em java use palavras-chave temporárias.

    Q: onde usar transiente?

    R: Geralmente, em java, podemos salvar dados em arquivos, adquirindo-os em variables ​​e gravando essas variables ​​em arquivos, esse processo é conhecido como Serialização. Agora, se quisermos evitar que os dados variables ​​sejam gravados no arquivo, faríamos essa variável como transitória.

    transitório int resultado = 10;

    Nota: as variables ​​transitórias não podem ser locais.

    Simplificando, a palavra-chave java transiente protege os campos da serialização serializada como partes do contador de campos não transientes.

    Neste trecho de código, nossa class abstrata BaseJob implementa a interface Serializable, nós nos estendemos do BaseJob, mas não precisamos serializar as fonts de dados locais e remotas; serialize apenas os campos organizationName e isSynced.

     public abstract class BaseJob implements Serializable{ public void ShouldRetryRun(){} } public class SyncOrganizationJob extends BaseJob { public String organizationName; public Boolean isSynced @Inject transient RemoteDataSource remoteDataSource; @Inject transient LocalDaoSource localDataSource; public SyncOrganizationJob(String organizationName) { super(new Params(BACKGROUND).groupBy(GROUP).requireNetwork().persist()); this.organizationName = organizationName; this.isSynced=isSynced; } }