Pourquoi Java a-t-il des champs transitoires ?
Le mot clé transient
en Java est utilisé pour indiquer qu'un champ ne doit pas faire partie du processus de sérialisation (c'est-à-dire enregistré, comme dans un fichier).
D'après la Spécification du langage Java, Java SE 7 Edition , Section 8.3.1.3. transient
Fields :
Les variables peuvent être marquées
transient
à indiquer qu'ils ne font pas partie du état persistant d'un objet.
Par exemple, vous pouvez avoir des champs dérivés d'autres champs et vous ne devez le faire que par programme plutôt que de conserver l'état via la sérialisation.
Voici une classe GalleryImage
qui contient une image et une vignette dérivée de l'image:
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();
}
}
Dans cet exemple, la variable thumbnailImage
est une image miniature générée en appelant la méthode generateThumbnail
.
Le champ thumbnailImage
est marqué avec transient
, de sorte que seul le image
original est sérialisé au lieu de conserver à la fois l'image d'origine et la vignette. Cela signifie que moins d'espace de stockage serait nécessaire pour enregistrer l'objet sérialisé. (Bien entendu, cela peut être souhaitable ou non, selon les exigences du système - ceci n’est qu’un exemple.)
Au moment de la désérialisation, la méthode readObject
est appelée pour effectuer les opérations nécessaires à la restauration de l'état de l'objet dans l'état dans lequel la sérialisation s'est produite. Ici, la vignette doit être générée, de sorte que la méthode readObject
est remplacée de sorte que la vignette soit générée en appelant la méthode generateThumbnail
.
Pour plus d'informations, le Découvrez les secrets de l'API de sérialisation Java article (disponible à l'origine sur Sun Developer Network) contient une section qui décrit l'utilisation de et présente un scénario dans lequel le mot clé transient
est utilisé pour empêcher la sérialisation. de certains champs.
Avant de comprendre le mot clé transient
, il faut comprendre le concept de sérialisation. Si le lecteur est au courant de la sérialisation, veuillez ignorer le premier point.
La sérialisation consiste à rendre l'état de l'objet persistant. Cela signifie que l'état de l'objet est converti en un flux d'octets à utiliser pour la persistance (par exemple, le stockage d'octets dans un fichier) ou le transfert (par exemple, l'envoi d'octets sur un réseau). De la même manière, nous pouvons utiliser la désérialisation pour ramener l'état de l'objet à partir d'octets. C'est l'un des concepts importants de la programmation Java car la sérialisation est principalement utilisée dans la programmation en réseau. Les objets devant être transmis via le réseau doivent être convertis en octets. Pour cela, chaque classe ou interface doit implémenter l'interface Serializable
. C'est une interface de marqueur sans aucune méthode.
transient
et son objectif?Par défaut, toutes les variables de l'objet sont converties en un état persistant. Dans certains cas, vous pouvez éviter la persistance de certaines variables car vous n’avez pas besoin de les conserver. Vous pouvez donc déclarer ces variables en tant que transient
. Si la variable est déclarée en tant que transient
, elle ne sera pas persistée. C’est l’objet principal du mot clé transient
.
Je veux expliquer les deux points ci-dessus avec l'exemple suivant:
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);
}
}
Et le résultat sera le suivant:
First Name : Steve
Middle Name : null
Last Name : Jobs
Middle Name est déclaré en tant que transient
et ne sera donc pas stocké dans la mémoire persistante.
Pour vous permettre de définir des variables que vous ne souhaitez pas sérialiser.
Dans un objet, vous pouvez avoir des informations que vous ne souhaitez pas sérialiser/persister (peut-être une référence à un objet de fabrique parent), ou peut-être que la sérialisation n'a pas de sens. Le fait de les marquer comme "transitoires" signifie que le mécanisme de sérialisation ignorera ces champs.
Ma petite contribution:
Qu'est-ce qu'un champ transitoire?
Fondamentalement, tout champ modifié avec le mot clé transient
est un champ transitoire.
Pourquoi les champs transitoires sont-ils nécessaires en Java?
Le mot clé transient
vous permet de contrôler le processus de sérialisation et d'exclure certaines propriétés d'objet de ce processus. Le processus de sérialisation est utilisé pour conserver les objets Java, principalement afin que leurs états puissent être préservés pendant leur transfert ou leur inactivité. Parfois, il est logique de ne pas sérialiser certains attributs d'un objet.
Quels champs devez-vous marquer comme transitoires?
Maintenant que nous connaissons l'objectif des champs du mot clé transient
et des éléments transitoires, il est important de savoir quels champs doivent être marqués. Les champs statiques ne sont pas non plus sérialisés, le mot-clé correspondant ferait également l'affaire. Mais cela pourrait ruiner la conception de votre classe; C'est ici que le mot clé transient
vient à la rescousse. J'essaie de ne pas permettre aux champs dont les valeurs peuvent être dérivées des autres d'être sérialisés, alors je les marque comme étant transitoires. Si vous avez un champ appelé interest
dont la valeur peut être calculée à partir d'autres champs (principal
, rate
& time
), il n'est pas nécessaire de le sérialiser.
Un autre bon exemple est avec l'article compte Word. Si vous enregistrez un article entier, il n'est vraiment pas nécessaire d'enregistrer le nombre de mots, car il peut être calculé lorsque l'article est "désérialisé". Ou pensez aux bûcherons; Les instances Logger
n'ont presque jamais besoin d'être sérialisées, elles peuvent donc être rendues transitoires.
Une variable transient
est une variable qui ne peut pas être sérialisée.
On pense par exemple aux cas où cela pourrait être utile, à savoir les variables qui n’ont de sens que dans le contexte d’une instance d’objet spécifique et qui deviennent invalides une fois que vous avez sérialisé et désérialisé cet objet. Dans ce cas, il est utile que ces variables deviennent plutôt null
afin que vous puissiez les réinitialiser avec des données utiles en cas de besoin.
transient
indique qu'un champ de classe n'a pas besoin d'être sérialisé . Le meilleur exemple est probablement un champ Thread
. Il n'y a généralement aucune raison de sérialiser une Thread
, car son état est très spécifique au flux.
Les systèmes de sérialisation autres que le Java natif peuvent également utiliser ce modificateur. Hibernate, par exemple, ne conservera pas les champs marqués de @Transient ni du modificateur transitoire . La terre cuite respecte également ce modificateur.
Je crois que la signification figurative du modificateur est "ce champ est réservé à une utilisation en mémoire. Ne le persistez pas et ne le déplacez pas en dehors de cette VM en particulier. Il n'est pas portable". c'est-à-dire que vous ne pouvez pas compter sur sa valeur dans un autre espace mémoire VM. Tout comme volatile signifie que vous ne pouvez pas compter sur certaines sémantiques de mémoire et de thread.
Parce que toutes les variables ne sont pas de nature sérialisable
Avant de répondre à cette question, je dois vous expliquer la SÉRIALISATION, car si vous comprenez ce que signifie la sérialisation dans un ordinateur scientifique, vous pouvez facilement comprendre ce mot-clé.
Sérialisation Lorsqu'un objet est transféré via le réseau/enregistré sur un support physique (fichier, ...), il doit être "sérialisé". La sérialisation convertit la série d'objets d'état d'octets. Ces octets sont envoyés sur le réseau/sauvegardés et l'objet est recréé à partir de ces octets.
Exemple
public class Foo implements Serializable
{
private String attr1;
private String attr2;
...
}
Maintenant, SI VOUS VOULEZ PAS TRANSFÉRER/ENREGISTRÉ LE CHAMP de cet objet SO, vous pouvez utiliser mot-clétransient
private transient attr2;
C'est nécessaire lorsque vous ne souhaitez pas partager des données sensibles associées à la sérialisation.
En termes simples, le mot clé Java transitoire protège les champs de la série Serialize en tant que parties de compteur des champs non transitoires.
Dans cet extrait de code, notre classe abstraite BaseJob implémente une interface sérialisable. Elle s'étend de BaseJob mais il n'est pas nécessaire de sérialiser les sources de données distantes et locales. sérialiser uniquement les champs organizationName et 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;
}
}
Selon google Sens transitoire == ne dure que peu de temps; transitoire.
Maintenant, si vous voulez que quelque chose soit transitoire en Java, utilisez le mot-clé transitoire.
Q: où utiliser transitoire?
A: Généralement en Java, nous pouvons enregistrer des données dans des fichiers en les acquérant dans des variables et en les écrivant dans des fichiers. Ce processus est appelé Sérialisation. Maintenant, si nous voulons éviter que des données variables soient écrites dans un fichier, nous ferions en sorte que cette variable soit transitoire.
transient int result=10;
Remarque: Les variables transitoires ne peuvent pas être locales.
Donnant un exemple supplémentaire pour clarifier les choses, .__ Veuillez lire la réponse acceptée…. Ici, je vais vous expliquer un autre exemple.
class Employee{
String name;
Date dob;
transient int age;
public int calculateAge(Date dob){
int age = 0;
//calculate age based on Date of birth
return age;
}
}
Ici, dans l'exemple ci-dessus, j'ai fait "age" comme transitoire. Lorsque j'écris age to file, sa valeur n'a pas besoin d'être stockée. J'ai une fonction ici qui calcule l'âge en fonction de la date de naissance. Nous pouvons utiliser des variables transitoires pour ces variables membres, que nous ne voulons pas écrire sur le disque.
J'espère que ça aide.!
Exemple de code simplifié pour mot-clé transitoire.
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);
}
}