Suppose you use some objects in your app, how do you copy your object? The most obvious way is to tell another object's simple assignment to another, just like this: obj2 = Obj1; But this method does not actually copy objects and just copy an object reference, change the words, still after you do this There is only one object, but there is more reference to the object. If this seemingly obvious method does not work properly, how do you actually copy an object? Why not try Object.clone? This method is available for all subclasses of Object. For example: Class A {Private Int x; Public A (INT I) {x = i;}} public class clonedemo1}} public class clonedemo1}} public class clonedemo1 {public static void main (string args []) throws clonenotsupportedException {a obj1 = new a (37); A Obj2 = (A) Obj1.clone ();}} This code triggers a compilation error because Object.clone is a protected method. So try again, change a method: class a {private int x; public a (int i) {x = i;} public object clone ()} public object clone () {Try {return super.clone ();} catch (CloneNotsuPortedException E) {throw new InternalError (e.toString ());}}} public class CloneDemo2 {public static void main (String args []) throws CloneNotSupportedException {A obj1 = new A (37); A obj2 = (A) obj1.clone ();}} In this method, it defines its own Clone method. It expands the object.clone method, clonedemo2 can be compiled, but a CloneNotSupportedException is throwing a CloneNotsupportException when you run it.
Some things are still missing here, you must let classes containing Clone methods to implement Cloneable interface, just like this: Class A Implements Cloneable {Private INT X; Public A (INT i) {x = i;} public object clone () { try {return super.clone ();} catch (CloneNotSupportedException e) {throw new InternalError (e.toString ());}} public int getx () {return x;}} public class CloneDemo3 {public static void main (String Args []) throws clonenotsupportedException {a obj1 = new a (37); a obj2 = (a) obj1.clone (); system.Out.println (obj2.getx ());}} success! CloneDemo3 can compile and produce the desired results: 37 You have learned that you must explicitly specify the Clone method and your class must implement the Cloneable interface. Cloneable is an example of the "Mark" interface, the interface itself does not specify anything, but Object.clone checks if it implements it, if not throws a ClonyNotsupportedException. Object.clone method makes a simple copy operation, copy all member variables of an object to a new object. In CloneDemo3, a.clone calls Object.clone, then Object.clone creates a new A object and copy the contents of the contents of the member variable that already exists to that new object. There is a lot of other things worth considering in CloneDemo3. One of them is that you can prevent the user from copying the class object. To do this, you can do not implement the Cloneable interface, so the copy operation will always throw an exception. However, in most cases, for your class plan and implement a Clone method, it can be better than the appropriate copy will be better. Another point is that you can support unconditional and conditional copies. CloneDemo3 is unconditional support copy, and the Clone method does not propagate ClonenotSupportedException exception. A more common method is conditional support class copy. In this case, the object itself can be copied, but the subclass of the object may not be copied. For conditional copies, the Clone method must declare that it can spread ClonenotsupportedException. One example of a conditional copy is an element of a collection class that can be copied only when those elements can be copied. Another way to have conditional copies is to achieve a suitable Clone method but does not implement a Cloneable interface. In this case, if you prefer, the subclass can support copy operation.
Copy operations may be very tricky, because Object.clone is a simple object member copy, sometimes this is not what you expect, for example: import java.util. *; Class a imports cloneable {public hashmap map; public a () { Map = new hashmap (); map.put ("key1", "value1"); map.put ("key2", "value2");} public object clone () {Try {return super.clone ();} Catch (clonenotsupportedexception e) {throw new interfacerror (e.tostring ());}}} public class clonedemo4 {public static void main (string args []) {a obj1 = new a (); a obj2 = (a) Obj1 .clone (); obj1.map.remove ("key1"); system.out.println (Obj2.map.get ("key1"));}} You may want CloneDemo4 to display the following results: value1 but actually it Display: What happened NULL? In CloneDemo4, an object contains a HashMAP reference. When the object is copied, the HashMap reference is also copied, which means that the copy generated object contains the original reference of the HashMap object. Therefore, when the content of HashMap in the original object changes, the content of the HashMap in the copy generated object is also updated.
To fix this problem, you can make the clone method more perfect: Import java.util. *; Class a imports cloneable {public hashmap map; public a () {map = new hashmap (); map.put ("key1", " Value1 "); map.put (" key2 "," value2 ");} public object clone () {Try {a aObj = (a) super.clone (); Aobj.map = (havehmap) map.clone () Return Aobj;} catch (clonenotsupportedException e) {throw new interface ());}}} public class cloneDemo5} public static void main (string args []) {a obj1 = new a (); a Obj2 = (A) obj1.clone (); obj1.map.remove ("key1"); system.out.println (obj2.map.get ("key1"));}}}}} clone5demo shows the following expectations: Value1 Clone5Demo Call Super.clone Create an object and copy the MAP member, and then call HashMap.clone to complete the copy of the HashMap type. This operation contains a new Hash table and copying members from the old one to the new haveh table. If two objects share a reference, just like clonedemo4, then you will usually encounter problems unless the reference is read-only, you need to avoid this problem, you need to implement the clone method to handle this problem. Another saying of this is that Object.clone is completed is the "shallow" copy of the object, that is, a simple member to the member's copy. It does not make "depth" copy, that is, the recursive copy of the object or array pointing to the object. You don't use "New CloneDemo5" to create an object, then call Super.clone is extremely important. You should adjust Super.clone at each level of the class level. This is because each level may have its own shared object problems. If you use "new" instead of super.clone, then your code is incorrect for subclasses that inherited from your class, and those code call your Clone method but receive an incorrect return type.
About copy, another thing you need to know is to copy any array, just simply call the clone method: public class clonedemo6 {public static void main (string args []) {int.com [] = new int {1, 2, 3}; int Vec2 [] = (int []) vec1.clone (); system.out.println (VEC2 [0] " VEC2 [1] " VEC2 [2]);} } The last important thing about copy is: it is a way to create and initialize a new object, but it is different from the call to a constructor. An example of this difference is Final members that are turned off, that is, those who state "final" but there is no initialization, they can only be assigned in the constructor. Here is an empty final member usage: public class clonedemo7 {private int A; private int b; private final long c; public clonedemo7 (int A, int b) {this.a = a; this.b = b; this .c = system.currenttimemillis ();} public static void main (string args []) {cloneDemo7 Obj = new cloneDemo7 (37, 47);}} In CloneDemo7 constructor, a final member "C" from the system clock A timestamp is obtained. What do you want to get if you have a copy of such types? Object.clone copies all member variables, but you think that time stamp members are set to the current system clock value. However, if a member is final type, you can only set that member in the constructor, and cannot be in the Clone method.
Here is an example of this problem: public class clonedemo8 {private int A; private int b; private final long c; public clonedemo8 (int A, int b) {this.a = a; this.b = b; this.c = System.currentTimeMillis ();} public CloneDemo8 (CloneDemo8 obj) {this.a = obj.a; this.b = obj.b; this.c = System.currentTimeMillis ();} public Object clone () throws CloneNotSupportedException {/ /this.c = System.currentTimeMillis (); return super.clone ();} public static void main (String args []) {CloneDemo8 obj = new CloneDemo8 (37, 47); CloneDemo8 obj2 = new CloneDemo8 (obj); }} If you want to cancel the comment program of the Final member, the comment is not compiled. For such a problem, we do not use the Clone method, the sample program uses a copy constructor. The parameters of the copy constructor are the same as their own type and implement a suitable copy logic.
(Translator Note: You need to pay attention to shared object problems when implementing a copy constructor. Due to the other two members in the example, there is no problem, but if your own class is the type of object, you can't use direct Assignment also uses a copy to perform or other suitable copy constructors, but if you need to use the type without copying method or a suitable copy constructor, you can't write your own appropriate copy constructor or copy method, Xin is the core class of Java basically does not exist this problem, but if you use other people's classes, you can't say it, so if you write your own class and want to make many people, then you must achieve a right copy. Method Maybe you think you can use the empty final member to initialize the problem with the system time when you declare those Final members, just like this: Class a imports cloneable {final long x = system.currentTimeMillis ); public Object clone () {try {return super.clone ();} catch (CloneNotSupportedException e) {throw new InternalError (e.toString ());}}} public class CloneDemo9 {public static void main (String args [ ]) {A obj1 = new a (); // sleep 100 ms Before doing clone, // to ensure unique timestamp try {thread.sleep (100);} catch (interruptedException e) {system.err.println (e) } A obj2 = (a) Obj1.cl One (); system.out.println (Obj1.x "" Obj2.x);}} This can not work, when you run this program, you can see the same value as Obj1.x and Obj2.x . This means that the usual object initialization is not performed when an object is generated, and you cannot set the value of the final member in the Clone method. So if a simple copy operation does not initialize a member correctly, you should not declare it as Final. Or you need to use a copy constructor as a replacement method of copy. (Translator Note: If you declare the member as Private and do not provide the value method of modifying it, then the effect and declare it as Final is the same.
Discussant: LMGL Participation: 3 Experts: 0 Posted: 2002-12-6 10:58 Wosing the following code results are "aaaa" string [] [] ss = new string [] [] {{"342 "," fs "}, {" 32 "," ger "}}; string [] [] s; s = (String [] []) ss.clone (); ss [1] [1] =" AAAA "; Based on system.out.println (s [1] [1]); CBAMI Participation: 19726 Experts: 4830 Published: 2002-12-6 1:27 PM That is a depth copy and shallow copy issues Please note the following in the article: If the two objects share a reference, just like clonedemo4, then you will usually encounter problems unless the reference is read-only, you need to avoid this problem, you need to implement it. Clone method handles this problem. Another saying of this is that Object.clone is completed is the "shallow" copy of the object, that is, a simple member to the member's copy. It does not make "depth" copy, that is, the recursive copy of the object or array pointing to the object.
Discussant: Kert Participation: 558 Experts: 520 Posted: 2002-12-6 1:31 Java's Clone should be the value of the clone object, not reference! However, if you don't know which is the value of an object, you will feel puzzle for Clone! See the following examples! 1.Private static void test1 () {PL ("Test1 --------"); string [] s = {"a", "a"}; string [] ss = (String " S.clone (); PL ("S: S); PL (" SS: " SS); SS [0] =" b "; PL (" SS [0] = " SS [0] ); PL ("s [0] =" s [0]); PL ("");} We here Clone a array object, the elements of the array are String, so the string is the value of this S. When we clone S, Java generates two equally String. And realize what we want. The output is: [pre] S: [ljava.lang.string; @ 7172eass: [ljava.lang.string; @ 2f6684ss [0] = BS [0] = a [/ pre] 2. Just the same example as the last reply Private static void test2 () {PL ("Test2 ---------"); string [] [] s = {{"a", "a"}, {"a", "a "}}; String [] [] ss = (String [] []) s.clone (); PL (" s = " s); PL (" ss = " ss); PL (" s [0 ] = " s [0]); PL (" Ss [0] = " SS [0]); PL (" S [1] = " S [1]); PL (" SS [1] = " SS [1]); SS [0] [0] =" b "; PL (" S [0] [0] = " S [0] [0]); PL (" SS [0] [ 0] = " SS [0] [0]); PL (" ");} Here we want Clone a two-dimensional array, and [i] wants [/ i] to each value of the clone array.
However, the result is willing to violate; [pre] test2 ----------- s = [[ljava.lang.string; @ 738798ss = [ljava.lang.string; @ 4b222fs [0] = [ljava. Lang.String; @ 3169f8ss [0] = [ljava.lang.string; @ 3169f8s [1] = [ljava.lang.string; @ 2457b6ss [1] = [ljava.lang.string; @ 2457b6s [0] [0 ] = BSS [0] [0] = b [/ pre] However, the fact that the facts that are well met with the principle of Clone. Java is a very good clone, our two-dimensional array. And generate a copy of it. Moreover, each value (one-dimensional array) in SS is identical to the original value. (We can see it clearly from the output). Because for an array object, the element of the array is the value of this object. Therefore, the element (value) of the two-dimensional array is a one-dimensional array. For array objects, Java uses it as a similar pointer. 3.Private static void test3 () {PL ("Test3 ---------"); string [] [] s = {{"a", "a"}, {"a", "a"}}; string [] [] ss = {(String []) s [0] .clone (), (String []) s [1] .clone ()}; PL ("s =" S); PL ("SS =" SS); PL ("S [0] =" S [0]); PL ("SS [0] =" SS [0]); PL ("S [ 1] = " S [1]); PL (" Ss [1] = " SS [1]); SS [0] [0] =" B "; PL (" S [0] [0] = " S [0] [0]); PL (" SS [0] [0] = " SS [0] [0]); PL (");} and when we change a Clone mode (depth Clone), we can see the result changes [pre] test3 ---------- s = [[ljava.lang.string; @ 7A78D3ss = [@ 7A78D3ss = [@ 129206s [ 0] = [ljava.lang.String; @ 30f13dss [0] = [ljava.lang.string; @ 2e000ds [1] = [ljava.lang.string; @ 55af5ss [1] = [ljava.lang.string; @ 169E11S [0] [0] = ASS [0] [0] = B [/ pre] --------- For ordinary Clone (shallow clone), virtual machine uses local methods, with similar Copy an object in the way. Therefore, it will seem to be a fascinating result. Therefore, when the Clone array or complex objects, the elements of the depth Clone, one of the one clone are required.