Today to introduce a concept, object cloning. This article has certain difficulty, please prepare mentally. Do not understand the words can read more than two times, or do not understand the words, you can leave a message below, I will see the situation to modify and supplement.
Cloning, the nature is to copy the object again, then why use cloning it? When do I need to use it? First look at a little chestnut:
For simplicity's sake, we're using a simple version of the goods class here.
Public classGoods {PrivateString title; Private DoublePrice ; PublicGoods (String Atitle,DoubleAprice) {Title=Atitle; Price=Aprice; } Public voidSetprice (DoublePrice ) { This. Price =Price ; } Public voidSettitle (String title) { This. title =Title }
For printing and exporting product information Public voidprint () {System.out.println ("Title:" +title+ "Price:" +Price ); }}
Then we'll use this class.
public class goodstest { public static void main (string[] args) {G Oods GOODSA = new Goods ("Goodsa", 20 = GOODSA; System.out.println ( before change: " "GOODSB" 50 after change: "
We create a goods object assigned to the variable GOODSA, then create a goods variable, and assign the GOODSA to it, first call the goods print method to output the information in both variables, Then call the Settitle and Setprice methods in the goods class to modify the object contents in the GOODSB, and then output the information in the two variables, and the following is the output:
before Change:Title:GoodsAPrice: 20.0TITLE:GOODSA Price:20.0 afterChange:Title:GoodsB Price: 50.0TITLE:GOODSB Price:50.0
Here we found the supernatural matter, we obviously modify the content of GOODSB, but the content of GOODSA also changed, this is why? Don't be impatient, and listen to me slowly.
In the Java language, data types are divided into value types (base data types) and reference types, and value types include simple data types such as int, double, Byte, Boolean, char, and reference types including complex types such as classes, interfaces, arrays, and so on. Assigning a value with an equal sign is a value pass, such as assigning an integer variable to another integer variable, which stores the value of the former, that is, the integer value in the variable, which is not a problem for basic types such as Int,double,char, but for objects, it is another matter. The GOODSA and GOODSB are all variables of the goods class object, but they do not store the contents of the Goods class object, they store its address, it is equivalent to a pointer in C + +, if you do not understand the pointer, then I would like to raise a chestnut. We have raised a chestnut before, compared to the computer is a warehouse administrator, memory compared to a warehouse, you want to use what type of variable, you need to register, and then the administrator will give you things, but if it is to assign you a house? This is not to move the house up to the register, but to register the address of the House, where the address is our class object variables recorded in the content, so when we assign a class object variable to another class object variable, such as GOODSB = GOODSA, Actually just assigns the object address of a to B, so that b also points to the address, so at this point, GOODSA and GOODSB operate on the same object.
So, if it's just a simple assignment, then the operation for GOODSA and GOODSB will affect the same object, which is obviously not our intention. You might also ask, "It's not good to be a new object directly, but sometimes if we need to save a copy of a GOODSA, it's not just a new object, but a series of assignment operations to set our new object to be the same as the Goodsa object. And the more complex the goods class, the more cumbersome this operation will be, in addition to the use of the Clone method for local optimization, the efficiency will be much faster, in short, is simple rough.
So how do you use clones? Here we are going to introduce our awesome Coax object class, all classes are subclasses of the object class, although we do not explicitly declare an inheritance relationship, but all classes are difficult to escape its clutches, it has two protected methods, one of which is the Clone method.
Let me show you a wave of correct Sao actions:
//you need to implement the Cloneable interface to use the Cloning method Public classGoodsImplementscloneable{PrivateString title; Private DoublePrice ; PublicGoods (String Atitle,DoubleAprice) {Title=Atitle; Price=Aprice; } Public voidSetprice (DoublePrice ) { This. Price =Price ; } Public voidSettitle (String title) { This. title =title; } Public voidprint () {System.out.println ("Title:" +title+ "Price:" +Price ); } //The clone method of the interface is overloaded here@OverrideprotectedObject Clone () {Goods g=NULL;
Here is the exception processing of the statement block, you can not understand, as long as you know that this is good to use, after the article will be described in detailTry{g= (Goods)Super. Clone (); }Catch(clonenotsupportedexception e) {System.out.println (e.tostring ()); } returnG; }}
In fact, there are only two changes, one is the definition of the class when the implementation of the Cloneable interface, the knowledge of the interface will be described in detail later, as long as the simple understanding is a specification, and then we overloaded the Clone method, and calls the Clone method of the parent class (Object). We can see that we do not have a new object, but instead use the Clone method of the parent class for cloning, the knowledge about try catch does not introduce too much here, then there will be a detailed explanation of the article, here only to understand as a try statement block is a possible error in the code, Catch catches this error and handles it.
Next we'll use the cloning method for this class:
Public class goodstest { publicstaticvoid main (string[] args) { new Goods ("GOODSA"); = (Goods) Goodsa.clone (); System.out.println ("Before Change:"); Goodsa.print (); Goodsb.print (); Goodsb.settitle ("GOODSB"); Goodsb.setprice (+); System.out.println ("After change:"); Goodsa.print (); Goodsb.print (); }}
We simply changed the assignment to the Clone method that called Goodsa and made the type conversion. The output is as follows:
before Change:Title:GoodsAPrice: 20.0TITLE:GOODSA Price:20.0 afterChange:Title:GoodsA Price: 20.0TITLE:GOODSB Price:50.0
Look, isn't that what we're going to do? Isn't it simple?
But don't be happy too early, about cloning, there is a little content to be introduced.
Clones are divided into shallow clones and deep clones. What's the difference between the two of us using shallow clones? Here's another chestnut, using a simplified version of the cart class:
Public classCartImplementscloneable{//instance DomainGoods goodslist =NewGoods ("", 0);//For simplicity's sake, there's only one item left. DoubleBudget = 0.0;//Budget//constructor Function PublicCart (Doubleabudget) {Budget=Abudget; } //Get Budget Public DoubleGetbudget () {returnbudget; } //Modify Budget Public voidSetbudget (Doubleabudget) {Budget=Abudget; } //It's just a simple assignment of a product. Public voidaddgoods (Goods Goods) {goodslist=(Goods) Goods.clone (); } //This is to demonstrate the added code, just modify the product title to a new title Public voidChangegoodstitle (String title) {Goodslist.settitle (title); } //Print product Information Public voidprint () {System.out.print ("Budget information in Cart:" +budget+ "Product Information:"); Goodslist.print (); } //Overloaded Clone method@OverrideprotectedObject Clone () {Cart C=NULL; Try{C= (Cart)Super. Clone (); }Catch(clonenotsupportedexception e) {e.printstacktrace (); } returnC; }}
This changes the goodslist from an array to a single object variable, for illustrative purposes only, and adds a Changegoodstitle method that modifies the title of the item to another title, and then modifies the Goodstest class:
Public classGoodstest { Public Static voidMain (string[] args) {Goods Goodsa=NewGoods ("Goodsa", 20);//Create a new Product object Cart Carta=NewCart (5000);//Create a new Shopping Cart object Carta.addgoods (GOODSA);//Add Item cart CARTB=(Cart) Carta.clone ();//Use light cloning
Output pre-modification information System.out.println ("Before Change:"); Carta.print (); Cartb.print ();
Modify the item title in Cart a Carta.changegoodstitle ("Newtitle");
Re-export the modified information System.out.println ("After change:"); Carta.print (); Cartb.print (); }}
Output information:
before budget information in Change:cart:5000.0 Product information: TITLE:GOODSA price:20.0cart Budget information:5000.0 product Information: TITLE:GOODSA price:20.0 afterchange:cart budget information: 5000.0 product information: Title:newtitle price:20.0in-cart budget information:5000.0 Product Information: Title:newtitle price:20.0
We found that while we were invoking the method in Carta to modify the product information in cart A, the information in shopping cart B was also modified because, when using the shallow clone mode, if the member variable is a complex type such as an object, only the value copy is used, as we described earlier, So although the CARTB is a copy of the Carta, but their member variables goodslist a common object, so entangled, obviously not the effect we want, this time we need to use a deep copy, just want to change the Cart class Clone method can:
@Override protected Object Clone () { null; Try { = (Cart)Super. Clone (); = (Goods) Goodslist.clone ();//Only This code is added, the commodity object is also cloned }catch ( Clonenotsupportedexception e) { e.printstacktrace (); } return c; }
Now let's run it again:
before budget information in Change:cart:5000.0 Product information: TITLE:GOODSA price:20.0cart Budget information:5000.0 product Information: TITLE:GOODSA price:20.0 afterchange:cart budget information: 5000.0 product information: Title:newtitle price:20.0in-cart budget information:5000.0 Product Information: TITLE:GOODSA price:20.0
This gives us the results we want.
In this way, the copy of the object is finished.
It?
Haha, do not crash, and there is a more complicated situation, that is, when your member variable also contains a reference type, such as the cart class has a CARTB class member variable, the CARTB class also has the reference type member variable, at this time, there is a problem of multi-layer cloning. Here we introduce a SAO operation, only need to understand, that is, the serialized object. The operation is as follows:
ImportJava.io.*; Public classCartImplementsserializable{//instance DomainGoods goodslist =NewGoods ("", 0);//For simplicity's sake, there's only one item left. DoubleBudget = 0.0;//Budget//constructor Function PublicCart (Doubleabudget) {Budget=Abudget; } //Get Budget Public DoubleGetbudget () {returnbudget; } //Modify Budget Public voidSetbudget (Doubleabudget) {Budget=Abudget; } //It's just a simple assignment of a product. Public voidaddgoods (Goods Goods) {goodslist=(Goods) Goods.clone (); } //This is to demonstrate the added code, just modify the product title to a new title Public voidChangegoodstitle (String title) {Goodslist.settitle (title); } //Print product Information Public voidprint () {System.out.print ("Budget information in Cart:" +budget+ "Product Information:"); Goodslist.print (); }//Here is mainly the Sao operation PublicObject Deepclone ()throwsIOException, optionaldataexception,classnotfoundexception {//write an object into the streamBytearrayoutputstream bo =NewBytearrayoutputstream (); ObjectOutputStream oo=NewObjectOutputStream (bo); Oo.writeobject ( This); //read it from the stream.Bytearrayinputstream bi =NewBytearrayinputstream (Bo.tobytearray ()); ObjectInputStream Oi=NewObjectInputStream (BI); return(Oi.readobject ()); }}
About this method I do not introduce more, we just need to know that there is a way to do, and later if you encounter the need to use this situation, you know how to deal with.
To summarize, the object cloning is to copy the current state of an object into another new object, two object variables pointing to different objects, shallow clone just call the Super.clone () method, the member variable is also a simple value copy, so when the member variable has an array, Objects and other complex types, there will be entangled confusion, deep copy not only call the Super.clone () method for object copy, the object of the complex type is also copied, so that two objects are no longer related, squarely.
At this point, the cloning of the object is really over, welcome to continue to pay attention! If you do not understand the question can leave a message. You are also welcome to criticize the big boys. Like my tutorial words remember to move small hands under the recommendation, also welcome to follow my blog.
Java 0 Basic Starter Series Day14 Java object cloning