Cet article discutera des 4 numéros suivants
1. Interface clonable java implémente une copie profonde
2. La sérialisation Java implémente une copie profonde
3. L'analyse de code source de clonage de bibliothèque binaire la plus rapide de la bibliothèque binaire
4. Comparaison des vitesses de plusieurs méthodes de copie
Je ne parlerai pas du concept de copie profonde dans cet article. Implémentation d'une copie profonde en C ++. Généralement, surchargez l'opérateur d'affectation "=" pour implémenter une copie profonde entre les objets de la même classe. Par conséquent, il est naturel qu'en Java, nous pouvons également définir une fonction de copie pour attribuer chaque propriété de l'objet dans la fonction. Cette méthode est simple et naturelle, mais il y a un problème fatal: si un jour un nouvel attribut qui nécessite une copie profonde est ajouté à la classe, la fonction de copie correspondante doit également être modifiée. Cette méthode apporte un grand inconvénient à l'extensibilité de la classe. Comment résoudre ce problème, examinons la méthode de mise en œuvre des chapitres 1, 2 et 3 et le test de vitesse de la section 4.
1. L'interface clonable java implémente la copie profonde <Br /> de cette manière, la classe doit implémenter la fonction de clone d'interface coloable et appeler super.clone dans la fonction de clone. Cette copie profonde de la méthode apporte également un autre problème. S'il existe des objets d'autres classes comme propriétés dans la classe, d'autres classes doivent également être surchargées et implémentées dans l'interface clonable. Voici un exemple. Dans l'exemple suivant, ComplexDO contient des objets Simpledo. Pour implémenter une copie profonde de complexdo, vous devez d'abord implémenter l'interface de clone de Simpledo:
classe publique Simpledo implémente clonable, sérialisable {private int x = 1; chaîne privée s = "simpledo"; @Override Protected Object Clone () lève ClonenotsupportEdException {Simpledo newClass = (Simpledo) super.clone (); return newClass; }} classe publique complexdo implémente clonable, sérialisable {private int x = 1; chaîne privée s = "complex"; entier privé a = 123; entier privé b = 1234; entier privé C = 1334455; chaîne privée s2 = "hehehe"; chaîne privée s3 = "hahaha"; ID long privé = 1233245L; Private ArrayList <Impledo> l = new ArrayList <Impledo> (); @Override public Object Clone () lève ClonenotsupporTedException {complexdo newClass = (complexdo) super.clone (); newClass.l = new ArrayList <Impledo> (); for (Simpledo Simple: this.l) {newClass.l.add ((Simpledo) Simple.clone ()); } return newClass; }} Il convient de noter que de nombreux articles disent que l'opérateur d'affectation du type de chaîne est une copie profonde, mais en fait, ceux qui utilisent des opérateurs d'affectation en Java sont des copies superficielles, mais pourquoi les articles avec des erreurs aussi évidents doivent-ils dire qu'il s'agit d'une copie profonde? Ma compréhension est que les attributs de chaîne et de type sont des types de base, et la méthode fournie sera de nouveaux objets tant que les changements de données internes sont conçus. Par conséquent, une opération de chaîne n'affectera pas la mémoire à l'origine. Par conséquent, d'une manière générale, les opérations d'affectation des classes de base telles que String sont des copies profondes.
Pour cette raison, lors de l'utilisation de l'épissage de chaîne de chaîne, une nouvelle mémoire doit être ouverte, de sorte que de nombreuses personnes recommandent d'utiliser StringBuilder au lieu de String pour l'épissage, car StringBuilder ne réapparaît que la mémoire plus grande lorsque la gamme de tableaux de char intégrée ne sera pas suffisante en instructions similaires pour StringBuilder.APPEND). Pour la culture opposée à l'épissage, il existe une fonction de sous-chaîne dans la chaîne. Lorsque vous utilisez la fonction de sous-chaîne, le tableau de char interne de la nouvelle chaîne est-il le même que la chaîne d'origine? C'est plus intéressant. Si vous êtes intéressé, vous pouvez comparer et vérifier l'implémentation de JDK1.6 et JKD1.7.
2. La sérialisation Java implémente une copie profonde
Le principe de cette méthode est d'utiliser la sérialisation Java pour sérialiser un objet dans un flux d'octets binaires, puis désérialiser et attribuer la valeur à un objet. Exemple de code:
Objet public seircopy (objet src) {try {bytearrayoutputStream byteout = new bytearrayoutputStream (); ObjectOutputStream out = new ObjectOutputStream (byteout); out.writeObject (SRC); ByteArrayInputStream bytein = new ByteArrayInputStream (byteout.ToByTearray ()); ObjectInputStream dans = new ObjectInputStream (bytein); Objet dest = in.readObject (); retour dest; } catch (exception e) {// faire un gestionnaire d'erreur renvoie null; }} Bien sûr, vous pouvez également utiliser JSON et d'autres bibliothèques sérialisées pour terminer la sérialisation. Cette méthode évite efficacement les lacunes extensibles de l'interface de clonabel. Une fonction peut essentiellement convenir à toutes les classes. L'inconvénient est qu'il s'agit d'une copie de mémoire relative. La sérialisation nécessite d'abord la conversion de l'objet en un flux d'octets binaires, puis désérialisant la re-co-coffrage du flux d'octet binaire en un morceau de mémoire d'objet, ce qui est relativement lent.
3. L'analyse de code source de clonage de bibliothèque binaire la plus rapide de la bibliothèque binaire
Dans le code source, la logique de traitement de base se trouve dans la classe Cloner.
Il y a deux liens récursifs:
Dans (1), FastClone complète les objets hérités de la classe d'interface IFastClone, c'est-à-dire qu'ils sont tous des copies des opérations de collecte;
Dans (2), CloneObject complète le processus d'obtention de chaque propriété de l'objet normal via le mécanisme de réflexion, puis d'attribution de valeurs aux propriétés de l'objet nouvellement généré en utilisant l'objénèse.
Cette méthode est très extensible. Non seulement vous pouvez compter sur son code existant pour terminer la copie profonde, mais vous pouvez également définir certaines méthodes de clonage et types qui ne nécessitent pas de clonage, ce qui est très flexible.
4. Comparaison des vitesses de plusieurs méthodes de copie
Les trois modes ci-dessus peuvent être utilisés pour terminer la copie en profondeur, et la méthode de copie la plus rapide est ce qui nous intéresse.
Tout d'abord, testez le code:
public void testClONEComplex () lève ClonenotsupportEdException {final int copycount = 1; List <complexdo> complexDolist = new ArrayList <Sebledo> (Copycount * 3); complexe complexe final = new complexdo (); // Calcul de la bibliothèque à deux côtés Long Start = System.CurrentTimemillis (); for (int i = 0; i <Copycount; ++ i) {final complexdo deepclone = clner.deepClone (complex); ComplexDolist.Add (DeepClone); } long fin = System.currentTimemillis (); System.out.println ("DeepClone Cost Time =" + (End-Start)); // Appel de la fonction Clone implémentée par l'interface clonable start = System.CurrentTimemillis (); for (int i = 0; i <Copycount; ++ i) {final complexdo interfaceClone = (complexdo) complex.clone (); complexdolist.add (interfaceclone); } end = System.currenttimemillis (); System.out.println ("InterfaceClone Cost Time =" + (End-Start)); // La sérialisation et la désérialisation génèrent un nouvel objet start = System.CurrentTimemillis (); for (int i = 0; i <Copycount; ++ i) {final complexdo seirlone = seircop (complex); complexdolist.add (seirclone); } end = System.currenttimemillis (); System.out.println ("SeirClone Cost Time =" + (End-Start)); }L'unité de résultats d'exécution est une milliseconde (ces données sont ignorées et ne calcule pas les points chauds Java et les GC possibles).
De ce tableau, nous pouvons tirer la conclusion:
1. La copie de l'interface clonable est la plus rapide, car elle n'implique que des copies de mémoire, mais si les attributs impliqués sont des objets plus communs, il est un peu difficile à écrire.
2. La copie de sérialisation / désérialisation est la plus lente
3. À l'aide de la bibliothèque de clonage, la copie du mécanisme de récursivité et de réflexion est plus lente que l'implémentation d'interface clonable, mais plus rapidement que la méthode de sérialisation.
Ce qui précède concerne cet article, j'espère qu'il sera utile à l'apprentissage de tout le monde.