Récemment, j'ai compilé les connaissances de base de Java, et les informations sur la sérialisation et la désérialisation de Java ont été réglées en détail. Je vais prendre une note ici, en espérant que cela aidera également les amis qui lisent cet article.
1. Le concept de sérialisation et de désérialisation
Le processus de conversion d'un objet en une séquence d'octets est appelé sérialisation d'un objet.
Le processus de restauration d'une séquence d'octets dans un objet est appelé désérialisation d'un objet.
Il existe deux utilisations principales pour la sérialisation des objets:
1) Enregistrer la séquence d'octets d'objets en permanence sur le disque dur, généralement dans un fichier;
2) Transférer la séquence d'octets d'objets sur le réseau.
Dans de nombreuses applications, certains objets doivent être sérialisés, de sorte qu'ils quittent l'espace mémoire et passent au disque dur physique pour un stockage à long terme. Par exemple, le plus courant est l'objet de session du serveur Web. Lorsque 100 000 utilisateurs accèdent simultanément, 100 000 objets de session peuvent apparaître et la mémoire peut ne pas être en mesure de le supporter. Par conséquent, le conteneur Web sérialisera d'abord certaines séisions sur le disque dur, et attendre qu'il soit utilisé, puis restaurer les objets enregistrés dans le disque dur à la mémoire.
Lorsque deux processus communiquent à distance, ils peuvent se envoyer différents types de données. Quel que soit le type de données, il sera transmis sur le réseau sous la forme d'une séquence binaire. L'expéditeur doit convertir cet objet Java en une séquence d'octets afin d'être transmis sur le réseau; Le récepteur doit restaurer les octets dans un objet Java.
2. API de sérialisation dans la bibliothèque de classe JDK
Java.io.ObjectOutputStream représente le flux de sortie de l'objet. Sa méthode WriteObject (objet OBJ) peut sérialiser l'objet OBJ spécifié par le paramètre et écrire la séquence d'octets obtenue à un flux de sortie cible.
Java.io.ObjectInputStream représente le flux d'entrée d'objet. Sa méthode readObject () lit les séquences d'octets à partir d'un flux d'entrée source, les désérialise dans un objet et les renvoie.
Seuls les objets de classes qui implémentent les interfaces sérialisables et externalisables peuvent être sérialisées. L'interface externalisable hérite de l'interface sérialisable. Les classes qui implémentent l'interface externalisable contrôlent complètement le comportement de sérialisation, tandis que les classes qui implémentent uniquement l'interface sérialisable peuvent adopter la méthode de sérialisation par défaut.
La sérialisation des objets comprend les étapes suivantes:
1) Créer un flux de sortie d'objet, qui peut envelopper un autre type de flux de sortie cible, tel que le flux de sortie du fichier;
2) Écrivez l'objet via la méthode writeObject () du flux de sortie de l'objet.
Les étapes pour désérialiser un objet sont les suivantes:
1) Créer un flux d'entrée d'objet qui peut envelopper un type différent de flux d'entrée source, tel que le flux d'entrée de fichier;
2) Lisez l'objet via la méthode readObject () du flux d'entrée d'objet.
Exemples de sérialisation des objets et de déséquence:
Définissez une classe de personne pour implémenter l'interface sérialisable
1 Importer Java.io.Serializable; 2 3 / ** 4 * <p> ClassName: Person <p> 5 * <p> Description: Test Object Serialization and Deserialization <p> 6 * @Author Xudp 7 * @version 1.0 V 8 * @createetime 2014-6-9 02:33:25 PM 9 * / 10 Public Class Person Implongés Sérializable {11 12 / ** 13 * Sérialisation ID14 * SerialVersionUID = -580978257827294399L; 16 Private Int Âge; 17 Nom de chaîne privée; 18 Sexe de chaîne privée; 19 20 public Int Getage () {21 RETOUR Age; 22} 23 24 public String GetName () Âge; 34} 35 36 public void setName (nom de chaîne) {37 this.name = name; 38} 39 40 public void setSex (String Sex) {41 this.sex = sexe; 42} 43}Sérialiser et désérialiser les objets de classe de la personne
import java.io.file; import java.io.fileInputStream; import java.io.filenotfoundException; import java.io.fileoutputStream; import java.io.ioexception; import java.io.objectInputStream; Importer java.io.objectOutStream; import Java.Text.MessageFormat; / ** *; TestObjSerializeAndDeserialize<p> * <p>Description: Serialization and deserialization of test objects<p> * @author xudp * @version 1.0 V * @createTime 2014-6-9 03:17:25 pm */public class TestObjSerializeAndDeserialize { public static void main(String[] args) throws Exception { SerializeSerson (); // Serialize Person Object Person P = DeserializeSon (); // Deserial Perons Object System.out.println (MessageFormat.Format ("name = {0}, age = {1}, sex = {2}", p.getName (), p.Getage (), p.getSex ()))); } / ** * Methodname: SerializeSerson * Description: Serialize Person Object * @Author xidp * @throws filenotfoundException * @throws ioException * / private static void SerializeSonS () lève FileNotFoundException, ioException {personne personne = new personne (); personne.setName ("gacl"); Person.Setage (25); personne.setSEX ("mâle"); // ObjectOutputStream Object Output Stream, stockez l'objet Person dans le fichier personne.txt sur le disque E et complétez l'opération de sérialisation de l'objet Person. ObjectOutputStream oo = new ObjectOutputStream (new FileOutputStream (nouveau fichier ("e: /person.txt"))); oo.writeObject (personne); System.out.println ("La sérialisation des objets de la personne a été avec succès!"); oo.close (); } / ** * Methodnname: DeserializeSerson * Description: DeserializeSon objet * @Author xudp * @return * @throws exception * @Throws ioException * / Private Static Person DeserializeSon () lève exception, ioException {ObjectInputStream Ois = new ObjectInStream (New FileInputam (new File ("e: /Person")); Personne personne = (personne) ois.readObject (); System.out.println ("Personne Object Desérialisation avec succès!"); personne de retour; }}Les résultats de l'exécution du code sont les suivants:
Après sérialiser la personne avec succès, un fichier personne.txt a été généré sur le disque E, tandis que la personne désérialisante est utilisée pour lire la personne.txt du disque E.
3. Le rôle de SerialVersionUid
Seri al versi UI D: signifie littéralement le numéro de version sérialisée. Toutes les classes qui implémentent l'interface sérialisable ont une variable statique représentant l'identifiant de version sérialisée.
Final statique privé long SerialVersionUid
Si SerialVersionUID n'est pas ajouté à la classe, le l'avertissement suivant apparaîtra.
Cliquer avec la souris affichera une boîte de dialogue qui génère SerialVersionUID, comme indiqué dans la figure ci-dessous:
Il existe deux façons de générer SerialVersionUID:
Le SerialVersionUid généré de cette manière est 1L, par exemple:
Long SerialVersionUID privé statique statique = 1L;
Le SerialVersionUid généré de cette manière est généré en fonction du nom de classe, du nom de l'interface, de la méthode et de l'attribut, etc., par exemple:
Final statique privé long SerialVersionUID = 4603642343377807741L;
Après l'ajout, l'avertissement n'apparaîtra pas, comme indiqué ci-dessous:
Après en parler, quelle est l'utilisation de SerialVersionUid (numéro de version sérialisée)? Utilisons l'exemple suivant pour illustrer le rôle de SerialVersionUID et voyez le code suivant:
1 import java.io.file; 2 import java.io.fileInputStream; 3 Importer Java.io.FilenotFoundException; 4 Import Java.io.FileOutputStream; 5 Importer java.io.ioException; 6 Importer java.io.ObjectInputStream; 7 Importer java.io.ObjectOutputStream; 8 Import Java.io.Serializable; 9 10 classe publique TestSerialVersionUid {11 12 public static void main (String [] args) lève une exception {13 serializomeromer (); // objet de sérialize Customer 14 Customer Customer = DeserializECustomer (); // objet du client désérial 15 System.out.println (client); 16} 17 18 / ** 19 * Méthode name: SérialiseCustomer 20 * Description: Firiariser 21 ** 19 * Méthodrome: Sérialise @Author xudp22 * @throws filenotfoundException23 * @throws ioException24 * / 25 private static void SerializECustomer () lance filenotFoundException, 26 ioException {27 Customer Customer = New Customer ("GACL", 25); 28 // ObjectOutStream objet Structure29 ObjectOutPutPutAm Oo = New ObjectOtStrem (New FidreoutStream (30 ObjectOutputPutAm Oo = New ObjectOtStremut Fichier ("e: /customer.txt"))); 31 oo.writeObject (client); 32 System.out.println ("Customer Object Serialization avec succès!"); 33 oo.close (); 34} 35 36 / ** 37 * Methodhnname: DeeRializeCustomer 38 * Description: DeerializeCustomer Object 39 * @author @throws exception42 * @throws ioException43 * / 44 Customer static privé DeserializECustomer () lève une exception, ioException {45 ObjectInputStream OIS = new ObjectInputStream (New FileInputStream (46 nouveau fichier ("e: /customer.txt"))); 47 Customer Customer = (Customer) Ois.ReadObject (); 48 System. La désérialisation des objets a réussi! "); 49 Client de retour; 50} 51} 52 53 / ** 54 * <p> ClassName: Client <p> 55 * <p> Description: Client implémente l'interface sérialisable et peut être sérialisé <p> 56 * @Author xudp57 * @version 1.0 v58 * @createtime 2014-6-9 04: 20: 1759 pm * / 60 CLASSE CLASSALITION CLASSITE {61 // Pas de SerialVersionUID62 Nom de chaîne privée; 63 Int privé; 64 65 Customer public (nom de chaîne, int Age) {66 this.name = name; 67 this.age = age; 68} 69 70 / * 71 * @methodname toString72 * @description réécriture le tostrin String75 * @see java.lang.object # toString () 76 * / 77 @ Override78 public String toString () {79 return "name =" + name + ", age =" + age; 80} 81}Résultats en cours:
La sérialisation et la désérialisation ont réussi.
Modifions la classe client et ajoutons un attribut sexuel supplémentaire, comme suit:
1 CLASS Le client implémente Serializable {2 // Aucun SerialVersionUID n'est défini dans le nom de chaîne privée de classe client 3; 4 Int Âge privé; 5 6 // nouvel attribut de sexe 7 Sexe à cordes privées; 8 9 Client public (nom de la chaîne, Int Age) {10 this.name = name; 11 this.age = Âge; 12} 13 14 Customer public (nom de chaîne, int Age, String Sex) {15 this.name = name; 16 this.age = age; 17 this.sex = sexe; 18} 19 20 / * 21 * @MethodName Tostring22 * @Descript xudp24 * @return String25 * @see java.lang.object # toString () 26 * / 27 @ Override28 public String toString () {29 return "name =" + name + ", age =" + age; 30} 31}Effectuez ensuite l'opération de déséquence et les informations d'exception suivantes seront lancées:
1 Exception dans Thread "Main" java.io.invalidclassexception: client; 2 Classe locale incompatible: 3 Stream ClassDesc SerialVersionUID = -88175599799432325, 4 Classe locale SerialVersionUID = -5182532647273106745
Cela signifie que la classe du flux de fichiers et la classe du chemin de classe, c'est-à-dire la classe modifiée, sont incompatibles. Ils sont sous les considérations de mécanisme de sécurité. Le programme lance une erreur et refuse de se charger. Et si nous avons vraiment besoin d'ajouter un champ ou une méthode après sérialisation? Que dois-je faire? C'est-à-dire pour spécifier vous-même vous-même. Dans l'exemple TestSerialVersionUid, si le SerialVersionUid de la classe client n'est pas spécifié, le compilateur Java effectuera automatiquement un algorithme de résumé pour cette classe, similaire à l'algorithme d'empreinte digitale. Tant que le fichier a un espace de plus, l'UID résultant sera complètement différent, ce qui peut être garanti que ce nombre est unique parmi tant de classes. Par conséquent, après avoir ajouté un champ, puisque le SerialVersionUid n'est pas spécifié, le compilateur génère un UID pour nous, ce qui n'est bien sûr pas le même que celui enregistré dans le fichier précédent, il y a donc deux erreurs avec des numéros de version de sérialisation incohérentes. Par conséquent, tant que nous spécifions nous-mêmes de SerialVersionid, nous pouvons ajouter un champ ou une méthode après sérialisation sans affecter la restauration ultérieure. L'objet restauré peut toujours être utilisé et il existe également plus de méthodes ou d'attributs à utiliser.
Ensuite, continuez à modifier la classe client et spécifiez un SerialVersionUID au client. Le code modifié est le suivant:
Class Client implémente Serializable {/ ** * SerialVersionUID (numéro de version sérialisée) définie dans la classe client * / private static final long SerialVersionUID = -5182532647273106745l; nom de chaîne privé; Âge privé; // nouvel attribut de sexe // sexe de chaîne privée; Client public (nom de chaîne, int age) {this.name = name; this.age = âge; } / * Customer public (nom de chaîne, Int Age, String Sex) {this.name = name; this.age = âge; this.sex = sexe; } * / / * * @Methodname toString * @description réécriture la méthode toString () de la classe d'objet * @author xudp * @return string * @see java.lang.object # toString () * / @Override public String toString () {return "name =" + name + ", Âge =" + Age; }}Réexécutez l'opération de sérialisation, sérialisez l'objet client vers le stockage de fichiers client.txt sur le disque dur local, puis modifiez la classe client et ajoutez l'attribut de sexe. Le code de classe client modifié est le suivant:
Class Client implémente Serializable {/ ** * SerialVersionUID (numéro de version sérialisée) définie dans la classe client * / private static final long SerialVersionUID = -5182532647273106745l; nom de chaîne privé; Âge privé; // nouvel attribut de sexe sexe de chaîne privée; Client public (nom de chaîne, int age) {this.name = name; this.age = âge; } Customer public (nom de chaîne, Int Age, String Sex) {this.name = name; this.age = âge; this.sex = sexe; } / * * @MethodName ToString * @Description Réécrivez la méthode toString () de la classe d'objets * @Author xudp * @return String * @see java.lang.object # toString () * / @Override public String toString () {return "name =" + name + ", Âge =" + Age; }}Effectuez l'opération de déséquence et la déséquence réussira cette fois, comme indiqué ci-dessous:
4. La valeur de SerialVersionUid
La valeur de SerialVersionUID est automatiquement générée par l'environnement d'exécution Java basé sur les détails internes de la classe. Si le code source de la classe est modifié et recompilé, la valeur du SerialVersionUid du fichier de classe nouvellement généré peut également changer.
La valeur par défaut du SerialVersionUid d'une classe dépend entièrement de l'implémentation du compilateur Java. Pour la même classe, la compilation avec différents compilateurs Java peut conduire à des combinaisons de série de sérials et peut également être la même. Pour améliorer l'indépendance et la certitude de SerialVersionUid, il est fortement recommandé de définir SerialVersionUid affiché dans une classe sérialisable, en lui attribuant une valeur claire.
Il y a deux objectifs pour définir explicitement SerialVersionUID:
1. Dans certains cas, il est prévu que différentes versions de la classe sont compatibles avec la sérialisation, il est donc nécessaire de s'assurer que différentes versions de la classe ont le même SerialVersionUid;
2. Dans certains cas, différentes versions de la classe ne devraient pas être compatibles avec la sérialisation, il est donc nécessaire de s'assurer que différentes versions de la classe ont différentes sériesousides de série.
Merci d'avoir lu, j'espère que cela peut vous aider. Merci pour votre soutien à ce site!