Qu'entend-on par "sérialisation d'objet"? Pouvez-vous s'il vous plaît expliquer avec quelques exemples?
La sérialisation est la conversion d'un objet en une série d'octets, de sorte que l'objet puisse facilement être sauvegardé dans un stockage persistant ou être transféré via un lien de communication. Le flux d'octets peut ensuite être désérialisé - converti en une réplique de l'objet d'origine.
Vous pouvez considérer la sérialisation comme le processus de conversion d'une instance d'objet en une séquence d'octets (qui peut être binaire ou non, en fonction de l'implémentation).
C'est très utile lorsque vous souhaitez transmettre des données d'un objet sur le réseau, par exemple d'une machine virtuelle à une autre.
En Java, le mécanisme de sérialisation est intégré à la plate-forme, mais vous devez implémenter l'interface Serializable pour rendre un objet sérialisable.
Vous pouvez également empêcher la sérialisation de certaines données de votre objet en marquant l'attribut comme étant transitoire .
Enfin, vous pouvez remplacer le mécanisme par défaut et fournir le vôtre; cela peut convenir dans certains cas particuliers. Pour ce faire, vous utilisez l’un des fonctionnalités cachées en Java .
Il est important de noter que ce qui est sérialisé est la "valeur" de l'objet, ou du contenu, et non la définition de la classe. Ainsi, les méthodes ne sont pas sérialisées.
Voici un exemple très basique avec des commentaires pour en faciliter la lecture:
import Java.io.*;
import Java.util.*;
// This class implements "Serializable" to let the system know
// it's ok to do it. You as programmer are aware of that.
public class SerializationSample implements Serializable {
// These attributes conform the "value" of the object.
// These two will be serialized;
private String aString = "The value of that string";
private int someInteger = 0;
// But this won't since it is marked as transient.
private transient List<File> unInterestingLongLongList;
// Main method to test.
public static void main( String [] args ) throws IOException {
// Create a sample object, that contains the default values.
SerializationSample instance = new SerializationSample();
// The "ObjectOutputStream" class has the default
// definition to serialize an object.
ObjectOutputStream oos = new ObjectOutputStream(
// By using "FileOutputStream" we will
// Write it to a File in the file system
// It could have been a Socket to another
// machine, a database, an in memory array, etc.
new FileOutputStream(new File("o.ser")));
// do the magic
oos.writeObject( instance );
// close the writing.
oos.close();
}
}
Lorsque nous exécutons ce programme, le fichier "o.ser" est créé et nous pouvons voir ce qui s'est passé derrière.
Si nous changeons la valeur de: someInteger en, par exemple Integer.MAX_VALUE , nous pouvons comparer la sortie pour voir quelle est la différence.
Voici une capture d'écran montrant précisément cette différence:
Pouvez-vous repérer les différences? ;)
Il existe un champ pertinent supplémentaire dans Java sérialisation: Le serialversionUID mais je suppose que c'est déjà trop long pour le couvrir.
Oser répondre à une question de 6 ans, en ajoutant simplement une compréhension de très haut niveau pour les débutants en Java
Qu'est-ce que la sérialisation?
Conversion d'un objet en octets et octets en objet (désérialisation).
quand utilise-t-on la sérialisation?
Quand on veut persister l'objet. Lorsque nous voulons que l'objet existe au-delà de la durée de vie de la machine virtuelle Java.
Exemple du monde réel:
ATM: lorsque le titulaire du compte tente de retirer de l'argent du serveur via ATM, les informations du titulaire du compte, telles que les détails du retrait, sont sérialisées et envoyées au serveur où les détails sont désérialisés et utilisés pour effectuer des opérations.
Comment la sérialisation est effectuée en Java.
Implémente Java.io.Serializable
interface (interface marqueur donc aucune méthode à implémenter).
Conservez l'objet: utilisez la classe Java.io.ObjectOutputStream
, un flux de filtrage enveloppant un flux d'octets de niveau inférieur (pour écrire l'objet dans des systèmes de fichiers ou transférer un objet aplati via un fil de réseau et reconstruit de l'autre côté).
writeObject(<<instance>>)
- pour écrire un objetreadObject()
- pour lire un objet sérialiséRappelles toi:
Lorsque vous sérialisez un objet, seul son état est enregistré, pas le fichier de classe ni les méthodes de l'objet.
Lorsque vous avez sérialisé un objet de 2 octets, vous voyez un fichier sérialisé de 51 octets.
Étapes de la sérialisation et de la désérialisation de l'objet.
Réponse pour: Comment s'est-il converti en fichier de 51 octets?
Java.lang.Object
.Si vous souhaitez en savoir plus sur les informations de service concernant Java Sérialisation, veuillez vérifier ceci lien .
Edit : Encore un bon lien à lire.
Cela répondra à quelques questions fréquentes:
Comment ne pas sérialiser un champ en classe.
Ans: utilise le mot-clé transitoire
Lorsque la classe enfant est sérialisée, la classe parent est-elle sérialisée?
Réponse: Non, si le parent n’étend pas, le champ parents de l’interface sérialisable n’est pas sérialisé.
Lorsque le parent est sérialisé, la classe enfant est-elle sérialisée?
Réponse: Oui, par défaut, la classe enfant est également sérialisée.
Comment éviter que la classe enfant ne soit sérialisée?
Ans: a. Remplacez les méthodes writeObject et readObject et jetez NotSerializableException
.
b. vous pouvez aussi marquer tous les champs transitoires dans la classe enfant.
La sérialisation prend un objet "vivant" en mémoire et le convertit dans un format qui peut être stocké quelque part (par exemple, en mémoire, sur disque) puis "désérialisé" dans un objet vivant.
J'ai aimé la façon dont @OscarRyz présente. Bien que je continue ici le histoire de la sérialisation qui a été écrit à l'origine par @amitgupta.
Même si connaître la structure de la classe de robots et disposer de données sérialisées, les scientifiques de Earth n’ont pas été en mesure de désérialiser les données, ce qui peut faire fonctionner les robots.
Exception in thread "main" Java.io.InvalidClassException:
SerializeMe; local class incompatible: stream classdesc
:
Les scientifiques de Mars attendaient le paiement complet. Une fois le paiement effectué, les scientifiques de Mars ont partagé le serialversionUID avec les scientifiques de la Terre. Le scientifique de la Terre l'a réglé sur la classe de robot et tout est devenu bien.
Mes deux cents de mon propre blog:
Voici une explication détaillée de la sérialisation : (mon propre blog)
Sérialisation:
La sérialisation est le processus de persistance de l'état d'un objet. Il est représenté et stocké sous la forme d'une séquence d'octets. Cela peut être stocké dans un fichier. Le processus permettant de lire l'état de l'objet à partir du fichier et de le restaurer s'appelle une désérialisation.
Quel est le besoin de sérialisation?
Dans l'architecture moderne, il est toujours nécessaire de stocker l'état de l'objet, puis de le récupérer. Par exemple, dans Hibernate, pour stocker un objet, nous devons rendre la classe Serializable. Ce qu’il fait, c’est que, une fois que l’objet est sauvegardé sous forme d’octets, il peut être transféré à un autre système, qui peut alors lire l’état et récupérer la classe. L'état de l'objet peut provenir d'une base de données ou d'un autre gestionnaire de volume ou d'un composant distinct. Avec l'aide de la sérialisation, nous pouvons récupérer l'état de l'objet.
Exemple de code et explication:
Voyons d'abord la classe d'objets:
public class Item implements Serializable{
/**
* This is the Serializable class
*/
private static final long serialVersionUID = 475918891428093041L;
private Long itemId;
private String itemName;
private transient Double itemCostPrice;
public Item(Long itemId, String itemName, Double itemCostPrice) {
super();
this.itemId = itemId;
this.itemName = itemName;
this.itemCostPrice = itemCostPrice;
}
public Long getItemId() {
return itemId;
}
@Override
public String toString() {
return "Item [itemId=" + itemId + ", itemName=" + itemName + ", itemCostPrice=" + itemCostPrice + "]";
}
public void setItemId(Long itemId) {
this.itemId = itemId;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public Double getItemCostPrice() {
return itemCostPrice;
}
public void setItemCostPrice(Double itemCostPrice) {
this.itemCostPrice = itemCostPrice;
}
}
Dans le code ci-dessus, on peut voir que la classe Item implémente Serializable .
C'est l'interface qui permet à une classe d'être sérialisable.
Nous pouvons maintenant voir qu'une variable appelée serialVersionUID est initialisée à la variable Long. Ce nombre est calculé par le compilateur en fonction de l'état de la classe et des attributs de la classe. C'est le numéro qui aidera le JVM à identifier l'état d'un objet lorsqu'il lit l'état de l'objet à partir du fichier.
Pour cela, nous pouvons consulter la documentation officielle d’Oracle:
L'exécution de la sérialisation associe à chaque classe sérialisable un numéro de version, appelé serialVersionUID, utilisé lors de la désérialisation pour vérifier que l'expéditeur et le destinataire d'un objet sérialisé ont chargé pour cet objet des classes compatibles avec la sérialisation. Si le destinataire a chargé une classe pour l'objet dont l'ID de série est différent de celui de la classe de l'expéditeur correspondante, la désérialisation génère une exception InvalidClassException. Une classe sérialisable peut déclarer explicitement son propre serialVersionUID en déclarant un champ nommé "serialVersionUID" qui doit être statique, final et de type long: ANY-ACCESS-MODIFIER statique final long serialVersionUID = 42L; Si une classe sérialisable ne déclare pas explicitement un serialVersionUID, l'exécution de la sérialisation calculera alors une valeur par défaut serialVersionUID pour cette classe, en fonction de divers aspects de la classe, comme décrit dans la spécification de sérialisation d'objet Java (TM). Cependant, il est vivement recommandé que toutes les classes sérialisables déclarent explicitement les valeurs serialVersionUID, car le calcul par défaut serialVersionUID est très sensible aux détails de classe qui peuvent varier en fonction de l'implémentation du compilateur et peuvent donc entraîner des exceptions InvalidClassException inattendues lors de la désérialisation. Par conséquent, pour garantir une valeur serialVersionUID cohérente dans différentes implémentations du compilateur Java, une classe sérialisable doit déclarer une valeur serialVersionUID explicite. Il est également fortement recommandé que les déclarations serialVersionUID explicites utilisent le modificateur private dans la mesure du possible, car elles ne s’appliquent qu’aux champs de la classe à déclaration immédiate. Les champs serialVersionUID ne sont pas utiles en tant que membres hérités.
Si vous avez remarqué qu'il existe un autre mot clé que nous avons utilisé, il s'agit de transitoire .
Si un champ n'est pas sérialisable, il doit être marqué comme étant transitoire. Ici, nous avons marqué le itemCostPrice comme transitoire et ne voulons pas qu'il soit écrit dans un fichier.
Voyons maintenant comment écrire l'état d'un objet dans le fichier et le lire à partir de là.
public class SerializationExample {
public static void main(String[] args){
serialize();
deserialize();
}
public static void serialize(){
Item item = new Item(1L,"Pen", 12.55);
System.out.println("Before Serialization" + item);
FileOutputStream fileOut;
try {
fileOut = new FileOutputStream("/tmp/item.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(item);
out.close();
fileOut.close();
System.out.println("Serialized data is saved in /tmp/item.ser");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void deserialize(){
Item item;
try {
FileInputStream fileIn = new FileInputStream("/tmp/item.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
item = (Item) in.readObject();
System.out.println("Serialized data is read from /tmp/item.ser");
System.out.println("After Deserialization" + item);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Dans ce qui précède, nous pouvons voir un exemple de sérialisation et de désérialisation d'un objet.
Pour cela nous avons utilisé deux classes. Pour sérialiser l'objet, nous avons utilisé ObjectOutputStream. Nous avons utilisé la méthode writeObject pour écrire l'objet dans le fichier.
Pour la désérialisation, nous avons utilisé ObjectInputStream, qui lit l'objet à partir du fichier. Il utilise readObject pour lire les données d'objet à partir du fichier.
La sortie du code ci-dessus serait comme:
Before SerializationItem [itemId=1, itemName=Pen, itemCostPrice=12.55]
Serialized data is saved in /tmp/item.ser
After DeserializationItem [itemId=1, itemName=Pen, itemCostPrice=null]
Notez que itemCostPrice de l'objet désérialisé est null car il n'a pas été écrit.
Nous avons déjà discuté des bases de Java Sérialisation dans la partie I de cet article.
Maintenant discutons en profondeur et comment cela fonctionne.
Commençons d’abord par le serialversionuid.
Le serialVersionUID est utilisé comme contrôle de version dans une classe Serializable.
Si vous ne déclarez pas explicitement un serialVersionUID, JVM le fera automatiquement pour vous, en fonction de différentes propriétés de la classe Serializable.
Algorithme de calcul de serialversionuid de Java (Plus de détails ici)
- Le nom de la classe.
- Les modificateurs de classe écrits sous la forme d'un entier 32 bits.
- Le nom de chaque interface trié par nom.
- Pour chaque champ de la classe trié par nom de champ (à l'exception des champs privés statiques et transitoires privés: nom du champ. Modificateurs du champ écrits sous la forme d'un entier de 32 bits. Descripteur du champ.
- Si un initialiseur de classe existe, écrivez ce qui suit: Le nom de la méthode,.
- Le modificateur de la méthode, Java.lang.reflect.Modifier.STATIC, écrit sous la forme d'un entier 32 bits.
- Le descripteur de la méthode, () V.
- Pour chaque constructeur non privé trié par nom de méthode et par signature: Le nom de la méthode,. Les modificateurs de la méthode écrits sous la forme d'un entier de 32 bits. Le descripteur de la méthode.
- Pour chaque méthode non privée triée par nom de méthode et par signature: Le nom de la méthode. Les modificateurs de la méthode écrits sous la forme d'un entier de 32 bits. Le descripteur de la méthode.
- L'algorithme SHA-1 est exécuté sur le flux d'octets produit par DataOutputStream et produit cinq valeurs de 32 bits sha [0..4]. La valeur de hachage est assemblée à partir des première et seconde valeurs 32 bits du résumé de message SHA-1. Si le résultat du résumé du message, les cinq mots de 32 bits H0 H1 H2 H3 H4, est dans un tableau de cinq valeurs int nommé sha, la valeur de hachage serait calculée comme suit:
long hash = ((sha[0] >>> 24) & 0xFF) |
> ((sha[0] >>> 16) & 0xFF) << 8 |
> ((sha[0] >>> 8) & 0xFF) << 16 |
> ((sha[0] >>> 0) & 0xFF) << 24 |
> ((sha[1] >>> 24) & 0xFF) << 32 |
> ((sha[1] >>> 16) & 0xFF) << 40 |
> ((sha[1] >>> 8) & 0xFF) << 48 |
> ((sha[1] >>> 0) & 0xFF) << 56;
Algorithme de sérialisation de Java
L'algorithme permettant de sérialiser un objet est décrit ci-dessous:
1. Il écrit les métadonnées de la classe associée à une instance.
2. Il écrit de manière récursive la description de la super-classe jusqu'à ce qu'il trouve Java.lang.object .
3. Une fois l’écriture des informations de métadonnées terminée, elle commence par les données réelles associées à l’instance. Mais cette fois, cela commence à partir de la classe supérieure.
4. Il écrit de manière récursive les données associées à l'instance, de la plus petite superclasse à la classe la plus dérivée.
Points à garder en mémoire:
Les champs statiques d'une classe ne peuvent pas être sérialisés.
public class A implements Serializable{
String s;
static String staticString = "I won't be serializable";
}
Si serialversionuid est différent dans la classe de lecture, il lève une exception InvalidClassException
.
Si une classe implémente sérialisable, toutes ses sous-classes le seront également.
public class A implements Serializable {....};
public class B extends A{...} //also Serializable
Si une classe a une référence d'une autre classe, toutes les références doivent être Serializable, sinon le processus de sérialisation ne sera pas exécuté. Dans ce cas, NotSerializableException est levé à l'exécution.
Par exemple:
public class B{
String s,
A a; // class A needs to be serializable i.e. it must implement Serializable
}
La sérialisation signifie des objets persistants en Java. Si vous souhaitez enregistrer l'état de l'objet et que vous souhaitez reconstruire l'état ultérieurement (éventuellement dans une autre machine virtuelle Java), vous pouvez utiliser la sérialisation.
Notez que les propriétés d'un objet ne vont être enregistrées. Si vous souhaitez ressusciter l'objet à nouveau, vous devez disposer du fichier de classe, car seules les variables membres seront stockées et non les fonctions membres.
par exemple:
ObjectInputStream oos = new ObjectInputStream(
new FileInputStream( new File("o.ser")) ) ;
SerializationSample SS = (SearializationSample) oos.readObject();
Searializable est une interface de marqueur qui indique que votre classe est sérialisable. Interface de marqueur signifie qu’il s’agit simplement d’une interface vide et que cette interface avertira la machine virtuelle que cette classe peut être rendue sérialisable.
La sérialisation est le processus de conversion de l'état d'un objet en bits afin qu'il puisse être stocké sur un disque dur. Lorsque vous désérialisez le même objet, il conservera son état ultérieurement. Il vous permet de recréer des objets sans avoir à enregistrer les propriétés des objets à la main.
La sérialisation consiste à enregistrer un objet sur un support de stockage (tel qu'un fichier ou une mémoire tampon) ou à le transmettre via une connexion réseau sous forme binaire. Les objets sérialisés sont indépendants de la machine virtuelle Java et peuvent être resérialisés par n'importe quelle machine virtuelle Java. Dans ce cas, l'état des objets "en mémoire" Java est converti en flux d'octets. Ce type de fichier ne peut pas être compris par l'utilisateur. Il s’agit d’un type d’objet spécial, réutilisé par la JVM (Java Virtual Machine). Ce processus de sérialisation d'un objet s'appelle également déflation ou marshalling d'un objet.
L'objet à sérialiser doit implémenter Java.io.Serializable
Interface. Le mécanisme de sérialisation par défaut d'un objet écrit la classe de l'objet, la signature de la classe et les valeurs de tous les champs non transitoires et non statiques.
class ObjectOutputStream extends Java.io.OutputStream implements ObjectOutput,
L'interface ObjectOutput
étend l'interface DataOutput
et ajoute des méthodes pour la sérialisation des objets et l'écriture d'octets dans le fichier. La ObjectOutputStream
étend Java.io.OutputStream
et implémente l'interface ObjectOutput
. Il sérialise des objets, des tableaux et d'autres valeurs dans un flux. Ainsi, le constructeur de ObjectOutputStream
s'écrit:
ObjectOutput ObjOut = new ObjectOutputStream(new FileOutputStream(f));
Le code ci-dessus a été utilisé pour créer l'instance de la classe ObjectOutput
avec le constructeur ObjectOutputStream( )
qui prend comme paramètre l'instance de FileOuputStream
.
L'interface ObjectOutput
est utilisée en implémentant la classe ObjectOutputStream
. La ObjectOutputStream
est construite pour sérialiser l'objet.
Désérialisation d'un objet en Java
L’opération opposée de la sérialisation est appelée désérialisation, c’est-à-dire que l’on extrait les données d’une série d’octets est appelé désérialisation, également appelée gonflement ou déformage.
ObjectInputStream
étend Java.io.InputStream
et implémente l'interface ObjectInput
. Il désérialise les objets, les tableaux et les autres valeurs d'un flux d'entrée. Ainsi, le constructeur de ObjectInputStream
s'écrit:
ObjectInputStream obj = new ObjectInputStream(new FileInputStream(f));
Le code ci-dessus du programme crée l'instance de la classe ObjectInputStream
pour désérialiser ce fichier qui a été sérialisé par la classe ObjectInputStream
. Le code ci-dessus crée l'instance à l'aide de l'instance de la classe FileInputStream
contenant l'objet de fichier spécifié à désérialiser car le constructeur ObjectInputStream()
a besoin du flux d'entrée.
Renvoie le fichier sous forme d'objet: http://www.tutorialspoint.com/Java/java_serialization.htm
import Java.io.*;
public class SerializeDemo
{
public static void main(String [] args)
{
Employee e = new Employee();
e.name = "Reyan ALi";
e.address = "Phokka Kuan, Ambehta Peer";
e.SSN = 11122333;
e.number = 101;
try
{
FileOutputStream fileOut =
new FileOutputStream("/tmp/employee.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
System.out.printf("Serialized data is saved in /tmp/employee.ser");
}catch(IOException i)
{
i.printStackTrace();
}
}
}
import Java.io.*;
public class DeserializeDemo
{
public static void main(String [] args)
{
Employee e = null;
try
{
FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee) in.readObject();
in.close();
fileIn.close();
}catch(IOException i)
{
i.printStackTrace();
return;
}catch(ClassNotFoundException c)
{
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("Deserialized Employee...");
System.out.println("Name: " + e.name);
System.out.println("Address: " + e.address);
System.out.println("SSN: " + e.SSN);
System.out.println("Number: " + e.number);
}
}
Serialization
est un mécanisme permettant de transformer un graphe d'objets Java en un tableau d'octets destinés au stockage (_to disk file
_) ou à la transmission (_across a network
_), alors en utilisant désérialisation nous pouvons restaurer le graphe des objets. Les graphiques d'objets sont restaurés correctement à l'aide d'un mécanisme de partage de référence. Mais avant de stocker, vérifiez si serialVersionUID du fichier d'entrée/réseau et le fichier .class serialVersionUID sont identiques. Sinon, lancez un _Java.io.InvalidClassException
_.
Chaque classe versionnée doit identifier la version de classe d'origine pour laquelle elle est capable d'écrire des flux et à partir de laquelle elle peut lire. Par exemple, une classe versionnée doit déclarer:
syntaxe serialVersionUID
_// ANY-ACCESS-MODIFIER static final long serialVersionUID = (64-bit has)L; private static final long serialVersionUID = 3487495895819393L;
_
serialVersionUID est essentiel au processus de sérialisation. Mais il est facultatif pour le développeur de l'ajouter dans le fichier source Java. Si aucun serialVersionUID n'est inclus, l'exécution de la sérialisation générera un serialVersionUID et l'associera à la classe. L'objet sérialisé contiendra ce serialVersionUID avec d'autres données.
Note - Il est fortement recommandé que toutes les classes sérialisables déclarent explicitement un serialVersionUID, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations
, et peuvent donc entraîner des conflits inattendus serialVersionUID lors de la désérialisation, ce qui entraîne l'échec de la désérialisation. .
Inspection des classes sérialisables
Un objet Java est uniquement sérialisable. si une classe ou l'une de ses superclasses implémente l'interface Java.io.Serializable ou sa sous-interface, Java.io.Externalizable.
Une classe doit implémenter interface Java.io.Serializable pour pouvoir sérialiser son objet. Serializable est une interface de marqueur utilisée pour informer le compilateur que la classe l'implémentant doit être ajoutée au comportement sérialisable. Ici Java La machine virtuelle (JVM) est responsable de sa sérialisation automatique.
mot-clé transitoire: _
Java.io.Serializable interface
_Lors de la sérialisation d'un objet, si nous ne voulons pas que certaines données membres de l'objet soient sérialisées, nous pouvons utiliser le modificateur transitoire. Le mot clé transitoire empêchera la sérialisation de ce membre de données.
- Les champs déclarés transitoires ou statiques sont ignorés par le processus de sérialisation.
_+--------------+--------+-------------------------------------+ | Flag Name | Value | Interpretation | +--------------+--------+-------------------------------------+ | ACC_VOLATILE | 0x0040 | Declared volatile; cannot be cached.| +--------------+--------+-------------------------------------+ |ACC_TRANSIENT | 0x0080 | Declared transient; not written or | | | | read by a persistent object manager.| +--------------+--------+-------------------------------------+
_
_class Employee implements Serializable {
private static final long serialVersionUID = 2L;
static int id;
int eno;
String name;
transient String password; // Using transient keyword means its not going to be Serialized.
}
_
L'implémentation de l'interface Externalizable permet à l'objet d'assumer un contrôle complet sur le contenu et le format du formulaire sérialisé de l'objet. Les méthodes de l'interface Externalizable, writeExternal et readExternal, sont appelées pour enregistrer et restaurer l'état des objets. Lorsqu'elles sont implémentées par une classe, elles peuvent écrire et lire leur propre état à l'aide de toutes les méthodes d'ObjectOutput et d'ObjectInput. Il est de la responsabilité des objets de gérer tout contrôle de version qui se produit.
_class Emp implements Externalizable {
int eno;
String name;
transient String password; // No use of transient, we need to take care of write and read.
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(eno);
out.writeUTF(name);
//out.writeUTF(password);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.eno = in.readInt();
this.name = in.readUTF();
//this.password = in.readUTF(); // Java.io.EOFException
}
}
_
Seuls les objets qui prennent en charge les flux Java.io.Serializable ou Java.io.Externalizable peuvent être des flux _written to
_/ _read from
_. La classe de chaque objet sérialisable est codée, y compris le nom de la classe et la signature de la classe, les valeurs des champs et des tableaux de l'objet et la fermeture de tout autre objet référencé à partir des objets initiaux.
Exemple sérialisable pour les fichiers
_public class SerializationDemo {
static String fileName = "D:/serializable_file.ser";
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
Employee emp = new Employee( );
Employee.id = 1; // Can not Serialize Class data.
emp.eno = 77;
emp.name = "Yash";
emp.password = "confidential";
objects_WriteRead(emp, fileName);
Emp e = new Emp( );
e.eno = 77;
e.name = "Yash";
e.password = "confidential";
objects_WriteRead_External(e, fileName);
/*String stubHost = "127.0.0.1";
Integer anyFreePort = 7777;
socketRead(anyFreePort); //Thread1
socketWrite(emp, stubHost, anyFreePort); //Thread2*/
}
public static void objects_WriteRead( Employee obj, String serFilename ) throws IOException{
FileOutputStream fos = new FileOutputStream( new File( serFilename ) );
ObjectOutputStream objectOut = new ObjectOutputStream( fos );
objectOut.writeObject( obj );
objectOut.close();
fos.close();
System.out.println("Data Stored in to a file");
try {
FileInputStream fis = new FileInputStream( new File( serFilename ) );
ObjectInputStream ois = new ObjectInputStream( fis );
Object readObject;
readObject = ois.readObject();
String calssName = readObject.getClass().getName();
System.out.println("Restoring Class Name : "+ calssName); // InvalidClassException
Employee emp = (Employee) readObject;
System.out.format("Obj[No:%s, Name:%s, Pass:%s]", emp.eno, emp.name, emp.password);
ois.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void objects_WriteRead_External( Emp obj, String serFilename ) throws IOException {
FileOutputStream fos = new FileOutputStream(new File( serFilename ));
ObjectOutputStream objectOut = new ObjectOutputStream( fos );
obj.writeExternal( objectOut );
objectOut.flush();
fos.close();
System.out.println("Data Stored in to a file");
try {
// create a new instance and read the assign the contents from stream.
Emp emp = new Emp();
FileInputStream fis = new FileInputStream(new File( serFilename ));
ObjectInputStream ois = new ObjectInputStream( fis );
emp.readExternal(ois);
System.out.format("Obj[No:%s, Name:%s, Pass:%s]", emp.eno, emp.name, emp.password);
ois.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
_
Exemple sérialisable sur le réseau
Etat de l'objet Distribution à travers différents espaces d'adresses, soit dans différents processus sur le même ordinateur, soit même dans plusieurs ordinateurs connectés via un réseau, mais fonctionnant ensemble en partageant des données et en invoquant des méthodes.
_/**
* Creates a stream socket and connects it to the specified port number on the named Host.
*/
public static void socketWrite(Employee objectToSend, String stubHost, Integer anyFreePort) {
try { // CLIENT - Stub[marshalling]
Socket client = new Socket(stubHost, anyFreePort);
ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
out.writeObject(objectToSend);
out.flush();
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// Creates a server socket, bound to the specified port.
public static void socketRead( Integer anyFreePort ) {
try { // SERVER - Stub[unmarshalling ]
ServerSocket serverSocket = new ServerSocket( anyFreePort );
System.out.println("Server serves on port and waiting for a client to communicate");
/*System.in.read();
System.in.read();*/
Socket socket = serverSocket.accept();
System.out.println("Client request to communicate on port server accepts it.");
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
Employee objectReceived = (Employee) in.readObject();
System.out.println("Server Obj : "+ objectReceived.name );
socket.close();
serverSocket.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
_
@voir
La sérialisation consiste à transformer un objet Java en un tableau d'octets, puis de nouveau en un objet avec son état préservé. Utile pour diverses choses comme l'envoi d'objets sur le réseau ou la mise en cache d'objets sur le disque.
Lisez-en plus sur ce court article qui explique très bien la programmation d'une partie du processus , puis passez à javadoc sérialisable. . Vous pouvez également être intéressé par la lecture de cette question connexe .
| * | Sérialisation d'une classe: Conversion d'un objet en octets et octet en objet (Désérialisation).
class NamCls implements Serializable
{
int NumVar;
String NamVar;
}
| => Object-Serialization est un processus de conversion de l'état d'un objet en vapeur d'octets.
| => La désérialisation d'objet est le processus permettant d'obtenir l'état d'un objet et de le stocker dans un objet (Java.lang.Object).
| => Un objet Java n'est sérialisable que si sa classe ou l'une de ses superclasses
| => Les champs statiques d'une classe ne peuvent pas être sérialisés.
class NamCls implements Serializable
{
int NumVar;
static String NamVar = "I won't be serializable";;
}
| => Si vous ne voulez pas sérialiser une variable d'une classe, utilisez le mot clé transitoire
class NamCls implements Serializable
{
int NumVar;
transient String NamVar;
}
| => Si une classe implémente serializable, toutes ses sous classes le seront aussi.
| => Si une classe a une référence d'une autre classe, toutes les références doivent être Serializable, sinon le processus de sérialisation ne sera pas exécuté. Dans ce cas,
NotSerializableException est levée à l'exécution.