Respostas:
A transient
palavra-chave em Java é usada para indicar que um campo não deve fazer parte do processo de serialização (que significa salvo, como em um arquivo).
Na Especificação da Linguagem Java, Java SE 7 Edition , Seção 8.3.1.3. transient
Campos :
As variáveis podem ser marcadas
transient
para indicar que não fazem parte do estado persistente de um objeto.
Por exemplo, você pode ter campos derivados de outros campos e deve ser feito apenas de forma programática, em vez de persistir o estado via serialização.
Aqui está uma GalleryImage
classe 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, thumbnailImage
é uma imagem em miniatura gerada chamando o generateThumbnail
método
O thumbnailImage
campo é marcado como transient
, portanto, apenas o original image
é serializado em vez de persistir tanto na imagem original quanto na miniatura. Isso significa que seria necessário menos armazenamento para salvar o objeto serializado. (Obviamente, isso pode ou não ser desejável, dependendo dos requisitos do sistema - este é apenas um exemplo.)
No momento da desserialização, o readObject
método é chamado para executar quaisquer operações necessárias para restaurar o estado do objeto de volta ao estado em que a serialização ocorreu. Aqui, a miniatura precisa ser gerada, para que o readObject
método seja substituído para que a miniatura seja gerada chamando o generateThumbnail
método.
Para obter informações adicionais, o artigo Descubra os segredos do Java Serialization API (originalmente disponível na Sun Developer Network) possui uma seção que discute o uso e apresenta um cenário em que a transient
palavra-chave é usada para impedir a serialização de determinados campos.
Antes de entender a transient
palavra - chave, é preciso entender o conceito de serialização. Se o leitor souber sobre serialização, pule o primeiro ponto.
Serialização é o processo de tornar o estado do objeto persistente. Isso significa que o estado do objeto é convertido em um fluxo de bytes para ser usado para persistir (por exemplo, armazenar bytes em um arquivo) ou transferir (por exemplo, enviar bytes pela rede). Da mesma maneira, podemos usar a desserialização para recuperar o estado do objeto de bytes. Este é um dos conceitos importantes na programação Java, porque a serialização é usada principalmente na programação de redes. Os objetos que precisam ser transmitidos pela rede precisam ser convertidos em bytes. Para esse fim, toda classe ou interface deve implementar a Serializable
interface. É uma interface de marcador sem nenhum método.
transient
palavra - chave e seu objetivo?Por padrão, todas as variáveis do objeto são convertidas em um estado persistente. Em alguns casos, convém evitar a persistência de algumas variáveis porque não é necessário persistir essas variáveis. Então você pode declarar essas variáveis como transient
. Se a variável for declarada como transient
, ela não será mantida. Esse é o principal objetivo da transient
palavra - chave.
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
Nome do meio é declarado como transient
, portanto, não será armazenado no armazenamento persistente.
NameFormatter
usado para dirigir toString()
. Ou qualquer outra coisa relacionada à configuração, exibição ou lógica de negócios ... em oposição aos dados.
Para permitir que você defina variáveis que você não deseja serializar.
Em um objeto, você pode ter informações que não deseja serializar / persistir (talvez uma referência a um objeto de fábrica pai) ou talvez não faça sentido serializar. Marcá-los como 'transitórios' 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 transient
palavra-chave é um campo transitório.
Por que os campos transitórios são necessários em Java?
A transient
palavra-chave fornece algum controle sobre o processo de serialização e permite excluir algumas propriedades do objeto desse processo. O processo de serialização é usado para persistir objetos 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 objeto.
Quais campos você deve marcar como transitório?
Agora sabemos o propósito dotransient
palavra-chave e campos transitórios, é importante saber quais campos marcar como transitórios. Os campos estáticos também não são serializados; portanto, a palavra-chave correspondente também funcionaria. Mas isso pode arruinar o design da sua classe; é aqui que a transient
palavra - chave vem em socorro. Tento não permitir que os campos cujos valores possam ser derivados de outros sejam serializados, marco-os como transitórios. Se você possui um campo chamado interest
cujo valor pode ser calculado a partir de outros campos ( principal
, rate
& time
), não é necessário serializá-lo.
Outro bom exemplo é com a contagem de palavras do artigo. Se você estiver salvando um artigo inteiro, não há realmente necessidade de salvar a contagem de palavras, pois ela pode ser calculada quando o artigo é "desserializado". Ou pense em madeireiros;Logger
As instâncias quase nunca precisam ser serializadas, para que possam se tornar transitórias.
transient
transient
Uma transient
variável é uma variável que pode não ser serializada.
Um exemplo de quando isso pode ser útil que vem à mente é: variáveis que só fazem sentido no contexto de uma instância de objeto específica e que se tornam inválidas depois de serializar e desserializar o objeto. Nesse caso, é útil que essas variáveis se tornem, null
para que você possa reinicializá-las com dados úteis quando necessário.
transient
é usado para indicar que um campo de classe não precisa ser serializado. Provavelmente, o melhor exemplo é um Thread
campo. Geralmente, não há razão para serializar a Thread
, pois seu estado é muito "específico do fluxo".
A
referenciar uma classe não serializável B
(como Thread
no seu exemplo), A
marque a referência, pois o transient
XOR deve substituir o processo de serialização padrão para fazer algo razoável com o B
XOR, assumindo que apenas as subclasses serializáveis B
são realmente referenciadas (portanto, a subclasse real deve cuidar de seu pai "ruim" B
). O XOR aceita que a serialização falhará. Em apenas um caso (marcado como transitório) B
é automaticamente e silenciosamente ignorado.
Sistemas de serialização diferentes do java nativo também podem usar esse modificador. O Hibernate, por exemplo, não persistirá nos campos marcados com @Transient ou com o modificador transitório . A terracota também respeita esse modificador.
Acredito que o significado figurativo do modificador é "esse campo é apenas para uso na memória. Não persista ou mova-o para fora desta VM específica de forma alguma. É não-portátil". ou seja, você não pode confiar em seu valor em outro espaço de memória da VM. Muito parecido com volátil significa que você não pode confiar em certa memória e semântica de threads.
transient
não seria uma palavra-chave se fosse projetada no momento. Eles provavelmente usariam uma anotação.
Porque nem todas as variáveis são de natureza serializável
Antes de responder a esta pergunta, devo explicar a SERIALIZAÇÃO , porque se você entender o que significa serialização em computadores científicos, poderá entender facilmente essa palavra-chave.
Serialização
Quando um objeto é transferido pela rede / salvo na mídia física (arquivo, ...), o objeto deve ser "serializado". A serialização converte a série de objetos de status de bytes. Esses bytes são enviados na rede / salvos e o objeto é recriado a partir desses bytes.
Exemplo
public class Foo implements Serializable
{
private String attr1;
private String attr2;
...
}
Agora, SE QUER NÃO TRANSFERIR / SALVAR o campo deste objeto , SO , você pode usar a palavra-chave transient
private transient attr2;
É necessário quando você não deseja compartilhar alguns dados confidenciais que acompanham a serialização.
Thread
(crédito para @AH por exemplo); nesse caso, você o marcaria como transitório. No entanto, um encadeamento não é um dado sensível por si só, não faz sentido lógico serializá-lo (e não é serializável).
De acordo com o significado transitório do google ==, durando apenas por um curto período de tempo; impermanente.
Agora, se você deseja tornar qualquer coisa transitória em java, use a palavra-chave transitória.
Q: onde usar transitório?
R: Geralmente em java, podemos salvar dados em arquivos adquirindo-os em variáveis e gravando essas variáveis em arquivos, esse processo é conhecido como serialização. Agora, se quisermos evitar que dados variáveis sejam gravados em arquivo, nós a tornaremos transitória.
transient int result=10;
Nota: variáveis transitórias não podem ser locais.
Simplificando, a palavra-chave java transitória protege os campos de Serialize, pois seus campos não transitórios se contrapõem.
Nesse trecho de código, nossa classe abstrata BaseJob implementa a interface serializável, estendemos a partir do BaseJob, mas não precisamos serializar as fontes de dados remotas e locais; 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;
}
}
Código de exemplo simplificado para palavra-chave transitória.
import java.io.*;
class NameStore implements Serializable {
private String firstName, lastName;
private transient String fullName;
public NameStore (String fName, String lName){
this.firstName = fName;
this.lastName = lName;
buildFullName();
}
private void buildFullName() {
// assume building fullName is compuational/memory intensive!
this.fullName = this.firstName + " " + this.lastName;
}
public String toString(){
return "First Name : " + this.firstName
+ "\nLast Name : " + this.lastName
+ "\nFull Name : " + this.fullName;
}
private void readObject(ObjectInputStream inputStream)
throws IOException, ClassNotFoundException
{
inputStream.defaultReadObject();
buildFullName();
}
}
public class TransientExample{
public static void main(String args[]) throws Exception {
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("ns"));
o.writeObject(new NameStore("Steve", "Jobs"));
o.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("ns"));
NameStore ns = (NameStore)in.readObject();
System.out.println(ns);
}
}
Um campo declarado com modificador transitório não participará do processo serializado. Quando um objeto é serializado (salvo em qualquer estado), os valores de seus campos transitórios são ignorados na representação serial, enquanto o campo diferente dos campos transitórios participará do processo de serialização. Esse é o principal objetivo da palavra-chave transitória.
@DoNotSerialize
?