Respuestas:
La transient
palabra clave en Java se usa para indicar que un campo no debe ser parte del proceso de serialización (lo que significa guardado, como en un archivo).
De la Especificación del lenguaje Java, Java SE 7 Edition , Sección 8.3.1.3. transient
Campos :
Las variables pueden marcarse
transient
para indicar que no son parte del estado persistente de un objeto.
Por ejemplo, puede tener campos que se derivan de otros campos, y solo debe hacerse de manera programática, en lugar de que el estado se mantenga a través de la serialización.
Aquí hay una GalleryImage
clase que contiene una imagen y una miniatura derivada de la imagen:
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();
}
}
En este ejemplo, thumbnailImage
es una imagen en miniatura que se genera al invocar el generateThumbnail
método.
El thumbnailImage
campo está marcado como transient
, por lo que solo el original image
se serializa en lugar de persistir tanto la imagen original como la imagen en miniatura. Esto significa que se necesitaría menos almacenamiento para guardar el objeto serializado. (Por supuesto, esto puede o no ser deseable dependiendo de los requisitos del sistema; esto es solo un ejemplo).
En el momento de la deserialización, readObject
se llama al método para realizar cualquier operación necesaria para restaurar el estado del objeto al estado en el que ocurrió la serialización. Aquí, la miniatura debe generarse, por lo que el readObject
método se anula para que la miniatura se genere llamando al generateThumbnail
método.
Para obtener información adicional, el artículo Descubre los secretos del API de serialización de Java (que originalmente estaba disponible en Sun Developer Network) tiene una sección que analiza el uso y presenta un escenario en el que la transient
palabra clave se usa para evitar la serialización de ciertos campos.
Antes de comprender la transient
palabra clave, uno debe comprender el concepto de serialización. Si el lector sabe acerca de la serialización, omita el primer punto.
La serialización es el proceso de hacer que el estado del objeto sea persistente. Eso significa que el estado del objeto se convierte en una secuencia de bytes que se utilizará para persistir (por ejemplo, almacenar bytes en un archivo) o transferir (por ejemplo, enviar bytes a través de una red). Del mismo modo, podemos usar la deserialización para recuperar el estado del objeto desde bytes. Este es uno de los conceptos importantes en la programación Java porque la serialización se usa principalmente en la programación de redes. Los objetos que deben transmitirse a través de la red deben convertirse en bytes. Para ese propósito, cada clase o interfaz debe implementar la Serializable
interfaz. Es una interfaz de marcador sin ningún método.
transient
palabra clave y su propósito?Por defecto, todas las variables del objeto se convierten en un estado persistente. En algunos casos, es posible que desee evitar la persistencia de algunas variables porque no tiene la necesidad de persistir esas variables. Entonces puedes declarar esas variables como transient
. Si la variable se declara como transient
, entonces no será persistente. Ese es el propósito principal de la transient
palabra clave.
Quiero explicar los dos puntos anteriores con el siguiente ejemplo:
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);
}
}
Y la salida será la siguiente:
First Name : Steve
Middle Name : null
Last Name : Jobs
Eltransient
segundo nombre se declara como , por lo que no se almacenará en el almacenamiento persistente.
NameFormatter
usado para conducir toString()
. O cualquier otra cosa relacionada con la configuración, o la visualización, o la lógica empresarial, ... a diferencia de los datos.
Para permitirle definir variables que no desea serializar.
En un objeto puede tener información que no desea serializar / persistir (tal vez una referencia a un objeto de fábrica principal), o tal vez no tenga sentido serializar. Marcarlos como 'transitorios' significa que el mecanismo de serialización ignorará estos campos.
Mi pequeña contribución:
¿Qué es un campo transitorio?
Básicamente, cualquier campo modificado con la transient
palabra clave es un campo transitorio.
¿Por qué se necesitan campos transitorios en Java?
La transient
palabra clave le da cierto control sobre el proceso de serialización y le permite excluir algunas propiedades de objeto de este proceso. El proceso de serialización se utiliza para persistir objetos Java, principalmente para que sus estados puedan conservarse mientras se transfieren o están inactivos. A veces, tiene sentido no serializar ciertos atributos de un objeto.
¿Qué campos debes marcar como transitorios?
Ahora sabemos el propósito de latransient
palabras clave y campos transitorios, es importante saber qué campos marcar como transitorios. Los campos estáticos tampoco están serializados, por lo que la palabra clave correspondiente también funcionaría. Pero esto podría arruinar su diseño de clase; Aquí es donde la transient
palabra clave viene al rescate. Intento no permitir que se serialicen los campos cuyos valores pueden derivarse de otros, por lo que los marco como transitorios. Si tiene un campo llamado interest
cuyo valor se puede calcular a partir de otros campos ( principal
, rate
& time
), no es necesario serializarlo.
Otro buen ejemplo es con el recuento de palabras del artículo. Si está guardando un artículo completo, realmente no es necesario guardar el recuento de palabras, ya que se puede calcular cuando el artículo se "deserializa". O piense en los madereros;Logger
Las instancias casi nunca necesitan ser serializadas, por lo que pueden hacerse transitorias.
transient
transient
Una transient
variable es una variable que puede no ser serializada.
Un ejemplo de cuándo esto puede ser útil que viene a la mente es, las variables que solo tienen sentido en el contexto de una instancia de objeto específica y que se vuelven inválidas una vez que haya serializado y deserializado el objeto. En ese caso, es útil que esas variables se conviertan en su null
lugar para que pueda reinicializarlas con datos útiles cuando sea necesario.
transient
se usa para indicar que un campo de clase no necesita ser serializado. Probablemente el mejor ejemplo es un Thread
campo. Por lo general, no hay razón para serializar a Thread
, ya que su estado es muy 'específico del flujo'.
A
referencia a una clase no serializable B
(como Thread
en su ejemplo), entonces A
debe marcar la referencia como transient
XOR debe anular el proceso de serialización predeterminado para hacer algo razonable con B
XOR suponiendo que solo las subclases serializables B
están realmente referenciadas (por lo que la subclase real debe cuidar a su padre "malo" B
) XOR acepta que la serialización fallará. En solo un caso (marcado como transitorio) B
se omite automática y silenciosamente.
Los sistemas de serialización que no sean el java nativo también pueden usar este modificador. Hibernate, por ejemplo, no persistirá en los campos marcados con @Transient o con el modificador transitorio . La terracota también respeta este modificador.
Creo que el significado figurativo del modificador es "este campo es solo para uso en memoria. No lo persista ni lo mueva fuera de esta VM en particular de ninguna manera. No es portátil". es decir, no puede confiar en su valor en otro espacio de memoria de VM. Al igual que volátil significa que no puede confiar en cierta memoria y semántica de subprocesos.
transient
no sería una palabra clave si fuera diseñada en este momento. Probablemente usarían una anotación.
Porque no todas las variables son de naturaleza serializable
Antes de responder a esta pregunta, debo explicarle la SERIALIZACIÓN , porque si comprende lo que significa la serialización en informática, puede comprender fácilmente esta palabra clave.
Serialización
Cuando un objeto se transfiere a través de la red / se guarda en un medio físico (archivo, ...), el objeto debe ser "serializado". La serialización convierte series de objetos de estado de bytes. Estos bytes se envían en la red / se guardan y el objeto se vuelve a crear a partir de estos bytes.
Ejemplo
public class Foo implements Serializable
{
private String attr1;
private String attr2;
...
}
Ahora, SI DESEA NO TRANSFERIR / GUARDAR el campo de este objeto SO , puede usar la palabra clave transient
private transient attr2;
Es necesario cuando no desea compartir algunos datos confidenciales que van con la serialización.
Thread
(crédito a @AH por ejemplo), en cuyo caso lo marcaría como transitorio. Sin embargo, un hilo no es información confidencial en sí misma, simplemente no tiene sentido lógico serializarlo (y no es serializable).
Según el significado transitorio de Google == que dura solo un corto tiempo; impermanente.
Ahora, si desea hacer algo transitorio en java, use una palabra clave transitoria.
P: ¿dónde usar transitorios?
R: Generalmente, en Java podemos guardar datos en archivos adquiriéndolos en variables y escribiendo esas variables en archivos, este proceso se conoce como serialización. Ahora, si queremos evitar que los datos variables se escriban en el archivo, haríamos que esa variable sea transitoria.
transient int result=10;
Nota: las variables transitorias no pueden ser locales.
En pocas palabras, la palabra clave java transitoria protege los campos de Serialize como sus contrapartes de campos no transitorios.
En este fragmento de código, nuestra clase abstracta BaseJob implementa la interfaz serializable, ampliamos desde BaseJob pero no necesitamos serializar las fuentes de datos remotas y locales; serializar solo los 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 ejemplo simplificado para transient-keyword.
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);
}
}
Un campo que se declara con un modificador transitorio no participará en el proceso serializado. Cuando un objeto se serializa (se guarda en cualquier estado), los valores de sus campos transitorios se ignoran en la representación en serie, mientras que el campo que no sea transitorio tomará parte en el proceso de serialización. Ese es el propósito principal de la palabra clave transitoria.
@DoNotSerialize
?