¿Por qué Java tiene campos transitorios?

¿Por qué Java tiene transitorio ¿campos?

preguntado el 26 de mayo de 09 a las 09:05

15 Respuestas

La transient La palabra clave en Java se usa para indicar que un campo no debe ser parte de la serialización (lo que significa guardado, como a un archivo) proceso.

Desde el Especificación del lenguaje Java, Java SE 7 Edition, Sección 8.3.1.3. transient Terrenos:

Las variables pueden estar marcadas transient para indicar que no forman parte del estado persistente de un objeto.

Por ejemplo, puede tener campos que se deriven de otros campos, y solo debe hacerse mediante programación, en lugar de que el estado persista 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, el thumbnailImage es una imagen en miniatura que se genera al invocar la generateThumbnail método.

La thumbnailImage el campo está marcado como transient, entonces solo el original image se serializa en lugar de conservar 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 ser deseable o no dependiendo de los requisitos del sistema; esto es solo un ejemplo).

En el momento de la deserialización, el readObject se llama al método para realizar las operaciones necesarias para restaurar el estado del objeto al estado en el que se produjo la serialización. Aquí, es necesario generar la miniatura, por lo que readObject se anula el método para que la miniatura se genere llamando al generateThumbnail método.

Para obtener información adicional, Descubra los secretos de la API de serialización de Java El artículo (que estaba disponible originalmente en Sun Developer Network) tiene una sección que analiza el uso y presenta un escenario en el que el transient La palabra clave se utiliza para evitar la serialización de ciertos campos.

respondido 06 nov., 18:15

Pero, ¿por qué es una palabra clave y no una anotación? @DoNotSerialize? - Elazar Leibovich

Supongo que esto se debe a una época en la que no había anotaciones en Java. - Pedro Wippermann

Me parece extraño que serializable sea interno a Java. Se puede implementar como una interfaz o clase abstracta que requiere que los usuarios anulen los métodos de lectura y escritura. - Caleb

@MJafar: readObject generalmente se encadena en mecanismos de deserialización y, por lo tanto, se llama automáticamente. Además, en muchos casos no es necesario anularlo: la implementación predeterminada funciona. - mike adler

@caleb probablemente porque lidiar con formatos binarios es increíblemente doloroso en Java debido a la falta de números enteros sin firmar. - pliegue a la derecha

Antes de comprender el transient palabra clave, 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 que se utilizará para persistir (por ejemplo, almacenar bytes en un archivo) o transferir (por ejemplo, enviar bytes a través de una red). De la misma manera, podemos usar la deserialización para recuperar el estado del objeto a partir de 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 el Serializable interfaz. Es una interfaz de marcador sin ningún método.

Ahora que es el transient palabra clave 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. Entonces puedes declarar esas variables como transient. Si la variable se declara como transient, entonces no se conservará. Ese es el objetivo 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

Segundo nombre se declara como transient, por lo que no se almacenará en el almacenamiento persistente.

Fuente

Respondido 14 Feb 19, 14:02

Este ejemplo está tomado de este código, puede leerlo aquí:javabeat.net/2009/02/qué-es-la-palabra-clave-transitoria-en-java - Krishna

Esta parte me parece extraña y posiblemente confusa: "Eso significa que el estado del objeto se convierte en un flujo de bytes y almacenado en un archivo". Me parece que la mayoría de las veces la serialización no implica escribir en un archivo (ejemplo: los ejemplos de redes que siguen) - García Hurtado

El ejemplo es malo, ya que el segundo nombre es claramente no una propiedad transitoria. - Rafael

@Raphael Para mí, el ejemplo es útil y al menos explica el concepto. ¿Daría un mejor ejemplo si estuviera al tanto? - Arafa

@Yoda Podríamos tener una referencia a un NameFormatter solía conducir toString(). O cualquier otra cosa relacionada con la configuración, la visualización o la lógica empresarial, ... en contraposición a los datos. - Rafael

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.

Respondido 14 Feb 19, 15:02

Mi pequeña contribución:

¿Qué es un campo transitorio?
Básicamente, cualquier campo modificado con el transient La palabra clave es un campo transitorio.

¿Por qué se necesitan campos transitorios en Java?
La transient La palabra clave le da cierto control sobre el proceso de serialización y le permite excluir algunas propiedades del objeto de este proceso. El proceso de serialización se utiliza para conservar 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 debería marcar como transitorio?
Ahora sabemos el propósito de la transient campos de palabras clave y transitorios, es importante saber qué campos marcar como transitorios. Los campos estáticos tampoco se serializan, por lo que la palabra clave correspondiente también funcionaría. Pero esto podría arruinar el diseño de su clase; aquí es donde el transient palabra clave viene al rescate. Intento no permitir que se serialicen 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 el recuento de palabras de los artículos. 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 madereros; Logger las instancias casi nunca necesitan ser serializadas, por lo que pueden convertirse en transitorias.

Respondido 21 ago 18, 17:08

Su 'oración simple' es simplemente una tautología. No explica nada. Estarías mejor sin él. - user207421

Esta es una buena explicación de dónde debería estar el campo transient - Arafa

el campo de interés y el recuento de palabras son buenos ejemplos de campos transitorios. - Tarun

Otro buen caso de uso: si su objeto tiene componentes como sockets y si desea serializar, ¿qué sucede con el socket? Si persistiera, después de deserializar, ¿qué retendría el socket? Tiene sentido hacer ese objeto socket como transient - mohamed siddiq

A transient variable es una variable que no se puede serializar.

Un ejemplo de cuándo esto podría ser útil que me viene a la mente son 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 se ha serializado y deserializado el objeto. En ese caso, es útil que esas variables se conviertan en null en su lugar, para que pueda reinicializarlos con datos útiles cuando sea necesario.

Respondido el 24 de enero de 18 a las 05:01

sí, algo como "contraseña o crediCardPin" miembros del campo de una clase. - mateen

Los sistemas de serialización distintos del nativo de Java también pueden utilizar este modificador. Hibernate, por ejemplo, no conservará los campos marcados con @Transitorio o transitorio modificador. Terracotta también respeta este modificador.

Creo que el significado figurado 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. Muy parecido volátiles significa que no puede confiar en cierta memoria y semántica de subprocesos.

contestado el 28 de mayo de 09 a las 03:05

Creo que transient no sería una palabra clave si estuviera diseñada en este momento. Probablemente usarían una anotación. - Joaquín Sauer

transient se utiliza para indicar que no es necesario serializar un campo de clase. Probablemente el mejor ejemplo es un Thread campo. Por lo general, no hay razón para serializar un Thread, ya que su estado es muy "específico de flujo".

respondido 26 nov., 13:22

Corrígeme si me equivoco, pero Thread no se puede serializar, por lo que se omitirá de todos modos. - TFennis

@TFennis: si es una clase serializable A hace referencia a una clase no serializable B (como el Thread en tu 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 asume que solo las subclases serializables de B en realidad se hace referencia (por lo que la subclase real debe cuidar de su padre "malo" B) XOR acepta que la serialización fallará. En un solo caso (marcado como transitorio) B se omite automática y silenciosamente. - AH

@TFennis No, causará una excepción. - user207421

@AH: ¿Por qué XOR? Creo que el código que hiciera cualquier combinación de esas cosas funcionaría, y algunas combinaciones podrían ser útiles (por ejemplo, anular el proceso de serialización predeterminado puede ser útil incluso si solo se hace referencia a subclases serializables de B, y viceversa). - Super gato

Porque no todas las variables son de naturaleza serializable

contestado el 26 de mayo de 09 a las 13:05

Proporcione más información cuando dé una respuesta. - danny gloudemans

Antes de responder a esta pregunta, debo explicarte el PUBLICACIÓN POR ENTREGAS, porque si comprende lo que significa serialización en informática científica, podrá comprender fácilmente esta palabra clave.

Publicación por entregas 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 a 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/SALVADO campo de este objeto SO, puedes usar keyword transient

private transient attr2;

Ejemplo

contestado el 23 de mayo de 17 a las 13:05

Es necesario cuando no desea compartir algunos datos confidenciales que acompañan a la serialización.

contestado el 26 de mayo de 09 a las 13:05

Hay casos de uso distintos de los datos confidenciales en los que es posible que no desee serializar un campo. Por ejemplo, probablemente nunca querrá serializar un Thread (crédito a @AH por ejemplo), en cuyo caso lo marcaría como transitorio. Sin embargo, un hilo no es un dato sensible en sí mismo, simplemente no tiene sentido lógico serializarlo (y no es serializable). - Glen3b

@ glen3b Ese caso no está excluido por esta respuesta. Ciertamente es necesario tal como están las cosas en el caso que menciona el cartel. - user207421

Según el significado transitorio de Google == que dura solo un corto tiempo; impermanente.

Ahora, si desea hacer algo transitorio en java, use la palabra clave transitoria.

P: ¿dónde usar transitorio?

A: 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 se escriban datos variables en un archivo, haríamos que esa variable sea transitoria.

transient int result=10;

Nota: las variables transitorias no pueden ser locales.

Respondido 16 Feb 19, 10:02

Código de ejemplo simplificado para palabra clave transitoria.

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);
    }
}

Respondido el 05 de junio de 19 a las 04:06

En pocas palabras, la palabra clave transitoria de Java protege los campos de la serialización como sus contrapartes de campos no transitorios.

En este fragmento de código, nuestra clase abstracta BaseJob implementa la interfaz serializable, se extiende desde BaseJob pero no necesitamos serializar las fuentes de datos locales y remotas; 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;

   }
}

respondido 14 nov., 17:13

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 sean los campos transitorios participará en el proceso de serialización. Ese es el propósito principal de la palabra clave transitoria.

Respondido el 24 de enero de 20 a las 09:01

Porque no todas las variables son de naturaleza serializable.

  1. La serialización y la deserialización son procesos de simetría, si no, no se puede esperar que se determine el resultado; en la mayoría de los casos, los valores indeterminados no tienen sentido;
  2. La serialización y la deserialización son idempotentes, lo que significa que puede realizar la serialización tantas veces como desee y el resultado es el mismo.

Entonces, si el Objeto puede existir en la memoria pero no en el disco, entonces el Objeto no se puede serializar, porque la máquina no puede restaurar el mapa de memoria cuando se realiza la deserialización. Por ejemplo, no puede serializar un Stream objeto.

No puede serializar un Connection objeto, porque su estado también depende del sitio remoto.

Respondido 04 Jul 20, 04:07

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.