java - variable - transient que es
¿Por qué Java tiene campos transitorios? (13)
¿Por qué Java tiene campos transitorios ?
Antes de entender la palabra clave transient
, uno tiene que entender el concepto de serialización. Si el lector conoce la serialización, omita el primer punto.
¿Qué es la serialización?
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 un flujo de bytes y se almacena en un archivo. De la misma manera, podemos usar la deserialización para recuperar el estado del objeto de los bytes. Este es uno de los conceptos importantes en la programación de Java porque la serialización se utiliza principalmente en la programación en red. 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 interfaz Serializable
. Es una interfaz de marcador sin ningún método.
Ahora, ¿cuál es la palabra clave transient
y su propósito?
De forma predeterminada, 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. Así que puedes declarar esas variables como transient
. Si la variable se declara como transient
, entonces no se persistirá. Ese es el propósito principal de la palabra clave transient
.
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
El segundo nombre se declara como transient
, por lo que no se almacenará en el almacenamiento persistente.
Antes de responder a esta pregunta, debo explicarle la SERIALIZACIÓN , porque si entiende lo que significa la serialización en una computadora científica, 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". Serialización convierte la serie 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 QUIERES NO TRANSFERIR / GUARDAR el campo de este objeto SO , puedes usar la palabra clave transient
private transient attr2;
En pocas palabras, la palabra clave transitoria de java protege los campos del estado Serializar como su contraparte de campos no transitorios.
En este fragmento de código, nuestra clase abstracta BaseJob implementa la interfaz Serializable, nos extendemos desde BaseJob pero no necesitamos serializar las fuentes de datos locales y remotas; Serializar solo los campos de nombre de organización 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;
}
}
La serialización es el proceso de guardar los estados de un objeto en un formato persistente (como la secuencia de archivos o la base de datos) y luego restaurarlos de la secuencia (deserialización). En Java, un objeto de una clase es serializable si la clase implementa la interfaz java.io.Serializable. Esta es una interfaz de marcador que le dice a la JVM que la clase es elegible para la serialización.
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
}
Hay tres puntos importantes en esta clase de modelo: Debe implementar la interfaz Serializable. De lo contrario, obtendremos una java.io.NotSerializableException al intentar serializar un objeto de la clase. Se declara una constante denominada serialVersionUID y se le asigna un valor largo:
private static final long serialVersionUID = 1234L;
Esta es una constante convencional que debe declararse cuando una clase implementa la interfaz Serializable. El UID de la versión de serie garantiza la compatibilidad entre las versiones serializadas y no serializadas de los objetos de una clase, ya que el proceso de serialización y deserialización puede ocurrir en diferentes computadoras y sistemas. Aunque esta declaración es opcional, siempre se recomienda declarar el serialVersionUID para una clase serializable.
Observe que el campo de contraseña está marcado como transitorio:
private transient String password;
Porque no queremos almacenar la contraseña al serializar el objeto. La regla es que cuando una variable se marca como transitoria, su objeto no se serializará durante la serialización.
Una variable transitoria es una variable que no puede ser serializada. Utiliza la palabra clave transitoria para indicar a la máquina virtual Java que la variable indicada no es parte del estado persistente del objeto.
Los modificadores de acceso soportados por Java son estáticos, finales, abstractos, sincronizados, nativos, volátiles, transitorios y estrictos.
La siguiente tabla proporciona la lista de especificadores y modificadores de acceso de Java que se pueden aplicar a variables, métodos y clases.
SPECIFIER/MODIFIER LOCAL VARIABLE INSTANCEVARIABLE METHOD CLASS
public NA A A A
protected NA A A NA
default A A A A
private NA A A NA
final A A A A
static NA A A NA
synchronized NA NA A NA
native NA NA A NA
volatile NA A NA NA
transient NA A NA NA
strictfp NA NA A A
Los sistemas de serialización distintos del java nativo también pueden usar este modificador. Hibernate, por ejemplo, no persistirá los campos marcados con @Transient o el modificador transitorio . 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 máquina virtual en particular. No es portátil". es decir, no puede confiar en su valor en otro espacio de memoria de VM. De manera similar a lo volátil significa que no puede confiar en cierta memoria y semántica de hilos.
Mi pequeña contribución:
¿Qué es un campo transitorio?
Básicamente, cualquier campo modificado con la palabra clave transient
es un campo transitorio.
¿Por qué se necesitan campos transitorios en Java?
La palabra clave transient
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 los 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 transitorios?
Ahora que conocemos el propósito de la palabra clave transient
y los campos transitorios, es importante saber qué campos marcar 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 el diseño de tu clase; aquí es donde la palabra clave transient
viene al rescate. Intento no permitir que los campos cuyos valores se pueden derivar de otros se serialicen, por lo que los marca como transitorios. Si tiene un campo llamado interest
cuyo valor puede calcularse a partir de otros campos ( principal
, rate
y time
), no es necesario serializarlo.
Otro buen ejemplo es con el número de palabras del artículo. Si está guardando un artículo completo, realmente no hay necesidad de guardar el recuento de palabras, ya que puede calcularse cuando el artículo se "deserializa". O piensa en los madereros; Logger
instancias del Logger
casi nunca necesitan ser serializadas, por lo que pueden hacerse transitorias.
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.
Porque no todas las variables son de carácter serializable.
Se necesita cuando no desea compartir algunos datos confidenciales que van con la serialización.
Una variable transient
es una variable que no puede ser serializada.
Un ejemplo de cuándo puede ser útil lo que viene a la mente es, 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 hacer que esas variables se vuelvan null
para que pueda reinicializarlas con datos útiles cuando sea necesario.
según el significado transitorio de Google == que dura solo un corto tiempo; impermanente.
Ahora si quieres hacer algo transitorio en java usa una palabra clave transitoria.
Q: donde usar transitorio?
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 un archivo, haríamos esa variable como transitoria.
resultado int transitorio = 10;
Nota: las variables transitorias no pueden ser locales.
transient
se utiliza para indicar que un campo de clase no necesita ser serializado. Probablemente el mejor ejemplo sea un campo Thread
. Generalmente no hay razón para serializar un Thread
, ya que su estado es muy ''específico del flujo''.
La palabra clave transient
en Java se usa para indicar que un campo no debe ser parte del proceso de serialización (lo que significa que se guardó, como en un archivo).
De la especificación del lenguaje Java, Java SE 7 Edition , Sección 8.3.1.3. Campos transient
:
Las variables pueden marcarse como
transient
para indicar que no forman parte del estado persistente de un objeto.
Por ejemplo, puede tener campos que se derivan de otros campos, y solo debe hacerlo de manera programática, en lugar de que el estado persista a través de la serialización.
Aquí hay una clase de GalleryImage
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 método generateThumbnail
.
El campo image
thumbnailImage
está marcado como transient
, por lo que solo la image
original se serializa en lugar de persistir tanto en la imagen original como en 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, se llama al método readObject
para realizar cualquier operación necesaria para restaurar el estado del objeto al estado en el que se produjo la serialización. Aquí, la miniatura debe generarse, por lo que el método readObject
se reemplaza para que la miniatura se genere llamando al método generateThumbnail
.
Para obtener información adicional, el artículo Descubra los secretos del API de Java Serialization (originalmente disponible en Sun Developer Network) tiene una sección que describe el uso y presenta un escenario en el que se usa la palabra clave transient
para evitar la serialización de ciertos campos.