JAVA in a pointer, the reference and the object's clone (switched from IBM)

One advantage of Java language is the repeal of the concept of pointers, but also led to a number of programmers in the programming often overlook the distinction between objects and references, this paper will attempt to clarify the concept. And because Java can not be a simple assignment to solve the object replication issues in the development process, often to be applied to clone () method to copy the object. This will let you know what a shadow clone and depth clone, awareness of their differences, advantages and disadvantages.
See this title, is not it a little puzzled: Java language clearly abolished the pointer, because the pointer is often convenient in the code at the same time also contributed to the root causes of insecurity, but also will become very complex and difficult to understand procedures, abuse of pointer to the code written in no way inferior to the use of already notorious "GOTO" statement. Java to abandon the concept of absolute pointer is extremely wise. But this is only in the Java language has no clear definition of indicators, in essence, a new statement for each return is a pointer reference, but most of the time in Java, do not care about how to do this "pointer", not as in the operation of C + + pointer so scared. The only lot of concern is that in time the object passed to the function. The following routine:
package reference;
class Obj (
String str = "init value";
public String toString () (
return str;
)
)
public class ObjRef (
Obj aObj = new Obj ();
int aInt = 11;
public void changeObj (Obj inObj) (
inObj.str = "changed value";
)
public void changePri (int inInt) (
inInt = 22;
)
public static void main (String [] args)
(
ObjRef oRef = new ObjRef ();

System.out.println ( "Before call changeObj () method:" + oRef.aObj);
oRef.changeObj (oRef.aObj);
System.out.println ( "After call changeObj () method:" + oRef.aObj);
System.out.println ("================== Print Primtive =================");
System.out.println ( "Before call changePri () method:" + oRef.aInt);
oRef.changePri (oRef.aInt);
System.out.println ( "After call changePri () method:" + oRef.aInt);
)
)
/ * RUN RESULT
Before call changeObj () method: init value
After call changeObj () method: changed value
================== Print Primtive =================
Before call changePri () method: 11
After call changePri () method: 11
*
* /

The main part of the code calls for two very similar ways, changeObj () and changePri (). The only difference is that they put an object as an input parameter, and the other in the Java basic types int as an input parameter. And in these two functions within the body of the input parameters have been changed. Seemingly the same way, the program output, the result is not the same. changeObj () method of a real change in the input parameters, while changePri () method of the input parameters without any change.
From this example we know that Java objects and basic data on the type of processing is not the same. , And C languages, when the Java basic data types (such as int, char, double, etc.) as the entry parameter passed to the function body, when the parameters passed into the function body within the local variables, the local variable is an input parameters, a copy of all the function body's internal operations are directed to this copy operation, after the end of the function implementation, the local variables also completed its mission, which affects less than a variable as an input parameter. The parameter in this way is called "value delivery." While in Java using the object as a parameter to pass the entrance is the default for "passing reference", that is just to pass the object as a "reference" this "reference" concept with the C language is the same as a pointer reference . When the input variable within the function body changes, essentially in the direct operation on this object.
In addition to the time-value function is "passing reference" in any use "=" to the object variable assignment at all times, "passing by reference." Such as:
package reference;
class PassObj
(
String str = "init value";
)
public class ObjPassValue
(
public static void main (String [] args)
(
PassObj objA = new PassObj ();
PassObj objB = objA;
objA.str = "changed in objA";
System.out.println ( "Print objB.str value:" + objB.str);
)
)
/ * RUN RESULT
Print objB.str value: changed in objA
* /

The first sentence is in memory to generate a new PassObj object, and then assign a reference to this PassObj variable objA, the second sentence is to PassObj object reference has assigned a variable objB. At this point objA and objB are two exactly the same variables, after a change in any objA equivalent right objB change.
Even if the Java language to understand the "pointer" concept may also inadvertently committed the following error.
Hashtable really be able to store object?
Consider the following very simple code, first declare a Hashtable and StringBuffer object, and then in four to StriingBuffer into the Hashtable object into the table, each placed in all of this StringBuffer object before the append () a number of new string:
package reference;
import java.util .*;
public class HashtableAdd (
public static void main (String [] args) (
Hashtable ht = new Hashtable ();
StringBuffer sb = new StringBuffer ();
sb.append ( "abc,");
ht.put ( "1", sb);
sb.append ( "def,");
ht.put ( "2", sb);
sb.append ( "mno,");
ht.put ( "3", sb);
sb.append ( "xyz.");
ht.put ( "4", sb);

int numObj = 0;
Enumeration it = ht.elements ();
while (it.hasMoreElements ()) (
System.out.print ( "get StringBufffer "+(++ numObj) +" from Hashtable: ");
System.out.println (it.nextElement ());
)
)
)

If you think the output results are:
get StringBufffer 1 from Hashtable: abc,
get StringBufffer 2 from Hashtable: abc, def,
get StringBufffer 3 from Hashtable: abc, def, mno,
get StringBufffer 4 from Hashtable: abc, def, mno, xyz.
Then you have to back and then take a closer look at a problem, the object as an entry parameter to the function, in essence, passing the object reference to the Hashtable passed StringBuffer object is to pass only a reference to this StringBuffer object! Hashtable table each time to put a StringBuffer, and does not generate a new StringBuffer object, only in the Hashtable into another table, a point to the same StringBuffer object reference only.
Hashtable table for storing any one of the StringBuffer object (more precisely, should be the object reference) of the changes are actually the same one "StringBuffer" changes. So, Hashtable can not really be able to store objects, but can only store object. Should also be aware of this principle with Hashtable similar to Vector, List, Map, Set, etc. are the same.
Above the actual output of the routine is:
/ * RUN RESULT
get StringBufffer 1 from Hashtable: abc, def, mno, xyz.
get StringBufffer 2 from Hashtable: abc, def, mno, xyz.
get StringBufffer 3 from Hashtable: abc, def, mno, xyz.
get StringBufffer 4 from Hashtable: abc, def, mno, xyz.
* /

Top

Classes, objects and references
Java basic concept is the class, class, including functions and variables. If you want to use class, it must generate an object class, this process is called "an instance of the class." There are several ways to the class instance into an object, the most common is to use "new" operator. After the class instance into an object, it means to occupy a space in memory storage instance. Want to piece of space operations must be applied to object. References in the Java language expression that is variable, but is this the type of a variable reference object. Although the syntax can generate an object directly after calling the object's function or variable, such as:
new String ( "Hello NDP")). substring (0,3) / / RETURN RESULT: Hel

However, no corresponding reference to the use of this object can only be limited to this statement of.
Generated: reference to an object as a parameter is always "pass" process occurs automatically, without human generation, nor the control of man-made reference to generation. The pass includes entrance to the objects as a function of the parameters, but also including the use of "=" to the object when the assignment.
Range: Only a partial reference, there is no local objects. References in the Java language expression is variable, but variable in the Java language, there is a scope, which can be partial or it can be global.
Survival: Program can only control the life cycle of reference. Lifetime of the object from the Java control. To use "new Object ()" statement to generate a new object is declared in the computer's memory, a regional storage object, only the Java garbage collector will decide at the appropriate time recovery of the object occupy memory.
There is no way to stop the application of this change.

Top

What is a "clone"?
The actual programming process, we often encounter such a situation: There is an object A, at some point A already contains a number of valid values, this time may require one and the same A new object B, and thereafter on the B will not affect any change in the value of A, ie, A and B are two separate objects, but the B's initial value is determined by the A objects. In the Java language, with a simple assignment statement can not meet this demand. To satisfy this demand, although there are many ways, but achieving clone () method is one of the easiest and most efficient means.
All Java classes inherit by default java.lang.Object class, in the java.lang.Object class has a method clone (). JDK API documentation for interpretation of this method will return a copy of the object Object. I want to clarify two points: First, copy the object returns a new object, rather than a reference. Second, the copy object using new operator returns the difference between the new object is this copy has already included some of the original object information, rather than the initial information on the object.

Top

How to use clone () method?
A typical call to clone () code is as follows:
class CloneClass implements Cloneable (
public int aInt;
public Object clone () (
CloneClass o = null;
try (
o = (CloneClass) super.clone ();
) catch (CloneNotSupportedException e) (
e.printStackTrace ();
)
return o;
)
)

There are three notable areas, one hopes to achieve the clone function of CloneClass class implements the Cloneable interface, this interface is part of java.lang package, java.lang package has been the default import classes, so do not need to write java. lang.Cloneable. Another note is that overloading of the clone () method. Finally, in clone () method call super.clone (), which also means that regardless of clone class inheritance structure is what, super.clone () directly or indirectly called java.lang.Object class clone () method. Next, a detailed explanation of what these points.
Should be said that third point is the most important, a careful look at the Object class clone () a native method, native methods are generally much higher than the efficiency of the non-native method java. This also explains why the use Object in the clone () method instead of the first new one class, then the information in the original object assigned to the new object, although it has also achieved a clone functionality. For the second point, we should also observe the Object class clone () or a protected attribute. This also means that if you want to use clone () method, you must inherit Object class, all of the classes in Java inherit the default Object class, also do not care about this. Then override clone () method. Another point to consider is to allow other classes to call this clone class clone () method, after the overload must clone () method of the property is set to public.
So why should we clone class Cloneable interface to achieve it? A little note of, Cloneable interface does not contain any method! In fact, this interface is only a sign, and this symbol is also only for the Object class clone () method, if the clone class does not implement Cloneable interface and call the Object's clone () method (which is called super.Clone ( ) method), then the Object's clone () method will throw an exception CloneNotSupportedException.
These are the most basic steps to clone and want to complete a successful clone, but also to understand what is "shadow clone" and "deep clone".

Top

What is a shadow clone?
The following example contains three classes UnCloneA, CloneB, CloneMain. CloneB class contains an instance of UnCloneA and a int type variable, and the heavy clone () method. CloneMain class initialization UnCloneA an instance of class b1, and then call the clone () method produces a b1 copy of b2. Finally look at the b1 and b2 the output:
package clone;
class UnCloneA (
private int i;
public UnCloneA (int ii) (i = ii;)
public void doubleValue () (i *= 2;)
public String toString () (
return Integer.toString (i);
)
)
class CloneB implements Cloneable (
public int aInt;
public UnCloneA unCA = new UnCloneA (111);
public Object clone () (
CloneB o = null;
try (
o = (CloneB) super.clone ();
) catch (CloneNotSupportedException e) (
e.printStackTrace ();
)
return o;
)
)
public class CloneMain (
public static void main (String [] a) (
CloneB b1 = new CloneB ();
b1.aInt = 11;
System.out.println ( "before clone, b1.aInt =" + b1.aInt);
System.out.println ( "before clone, b1.unCA =" + b1.unCA);

CloneB b2 = (CloneB) b1.clone ();
b2.aInt = 22;
b2.unCA.doubleValue ();
System.out.println ("=================================");
System.out.println ( "after clone, b1.aInt =" + b1.aInt);
System.out.println ( "after clone, b1.unCA =" + b1.unCA);
System.out.println ("=================================");
System.out.println ( "after clone, b2.aInt =" + b2.aInt);
System.out.println ( "after clone, b2.unCA =" + b2.unCA);
)
)
/ ** RUN RESULT:
before clone, b1.aInt = 11
before clone, b1.unCA = 111
=================================
after clone, b1.aInt = 11
after clone, b1.unCA = 222
=================================
after clone, b2.aInt = 22
after clone, b2.unCA = 222
* /

The results show that the output variable of type int and UnCloneA instances aInt object unCA the clone results to differ, int type is the real being clone, because the change in the aInt variable b2, b1 of the aInt of no impact, that is, b2.aInt and have occupied a different b1.aInt memory space, b2.aInt is a true copy of b1.aInt. On the contrary, the change of b2.unCA has also changed b1.unCA, obviously, b2.unCA and b1.unCA merely point to the same object in different reference! It can be seen, call the Object class clone () method of the effect is: the first in memory to open up a space like the original object, and then copy the original object as is the content. Of basic data types, such operation is no problem, but for non-basic types of variables, we know that they saved only a reference to an object, which later led to clone the non-basic types of variables and the original object variable pointing to the corresponding is the same object.
Most of the time, this clone results are often not what we want the results, this clone is also known as a "shadow clone". To get b2.unCA point and b2.unCA different audiences, but also in b2.unCA The information contained b1.unCA as the initial information, it is necessary to achieve deep clone.

Top

How in-depth clone?
The above example into a deep clone is very simple, requires two changes: First, let UnCloneA class also the same realization and CloneB class clone function (to achieve Cloneable interface, override clone () method). Second, in CloneB the clone () method by adding a o.unCA = (UnCloneA) unCA.clone ();
Procedures are as follows:
package clone.ext;
class UnCloneA implements Cloneable (
private int i;
public UnCloneA (int ii) (i = ii;)
public void doubleValue () (i *= 2;)
public String toString () (
return Integer.toString (i);
)
public Object clone () (
UnCloneA o = null;
try (
o = (UnCloneA) super.clone ();
) catch (CloneNotSupportedException e) (
e.printStackTrace ();
)
return o;
)
)
class CloneB implements Cloneable (
public int aInt;
public UnCloneA unCA = new UnCloneA (111);
public Object clone () (
CloneB o = null;
try (
o = (CloneB) super.clone ();
) catch (CloneNotSupportedException e) (
e.printStackTrace ();
)
o.unCA = (UnCloneA) unCA.clone ();
return o;
)
)
public class CloneMain (
public static void main (String [] a) (
CloneB b1 = new CloneB ();
b1.aInt = 11;
System.out.println ( "before clone, b1.aInt =" + b1.aInt);
System.out.println ( "before clone, b1.unCA =" + b1.unCA);

CloneB b2 = (CloneB) b1.clone ();
b2.aInt = 22;
b2.unCA.doubleValue ();
System.out.println ("=================================");
System.out.println ( "after clone, b1.aInt =" + b1.aInt);
System.out.println ( "after clone, b1.unCA =" + b1.unCA);
System.out.println ("=================================");
System.out.println ( "after clone, b2.aInt =" + b2.aInt);
System.out.println ( "after clone, b2.unCA =" + b2.unCA);
)
)
/ ** RUN RESULT:
before clone, b1.aInt = 11
before clone, b1.unCA = 111
=================================
after clone, b1.aInt = 11
after clone, b1.unCA = 111
=================================
after clone, b2.aInt = 22
after clone, b2.unCA = 222
* /

As can be seen, now b2.unCA changes on b1.unCA no impact. At this point b1.unCA with b2.unCA points to two different UnCloneA instance, but also in CloneB b2 = (CloneB) b1.clone (); call the moment of b1 and b2 have the same value, where, b1.i = b2.i = 11.
To know that not all classes can realize the depth of the clone. For example, if the above CloneB class UnCloneA type variable into a StringBuffer type, look at the JDK API on the StringBuffer instructions, StringBuffer does not override clone () method, is more serious is that StringBuffer is a final class, which is can be used to say that we do not inherit an indirect way to achieve the StringBuffer to clone. If a class contains a StringBuffer type object or a similar type and StringBuffer objects, we have two choices: either achieve only a shadow clone, either in class clone () method, plus one (assuming that SringBuffer object, and variable the name is still unCA): o.unCA = new StringBuffer (unCA.toString ()); / / the original is: o.unCA = (UnCloneA) unCA.clone ();
Would also like to know is addition to the basic data types can be automatically clone the depth beyond, String object is an exception, its clone the performance seems to have been achieved after a deep clone, although this is only an illusion, but it has greatly facilitated our programming.

Top

Clone of the difference between String and StringBuffer
Should be made clear is that this is not to highlight the difference between String and StringBuffer, but this example can also see the String class, some unusual places.
The following example consists of two classes, CloneC class contains a String type variable, and a StringBuffer type variable, and implements clone () method. The StrClone class declared CloneC type variable c1, then c1 is called the clone () method to generate c1 copy c2, in the c2 of the String and StringBuffer type variable changes, with the corresponding method of printing results:
package clone;
class CloneC implements Cloneable (
public String str;
public StringBuffer strBuff;
public Object clone () (
CloneC o = null;
try (
o = (CloneC) super.clone ();
) catch (CloneNotSupportedException e) (
e.printStackTrace ();
)
return o;
)

)
public class StrClone (
public static void main (String [] a) (
CloneC c1 = new CloneC ();
c1.str = new String ( "initializeStr");
c1.strBuff = new StringBuffer ( "initializeStrBuff");
System.out.println ( "before clone, c1.str =" + c1.str);
System.out.println ( "before clone, c1.strBuff =" + c1.strBuff);

CloneC c2 = (CloneC) c1.clone ();
c2.str = c2.str.substring (0,5);
c2.strBuff = c2.strBuff.append ( "change strBuff clone");
System.out.println ("=================================");
System.out.println ( "after clone, c1.str =" + c1.str);
System.out.println ( "after clone, c1.strBuff =" + c1.strBuff);
System.out.println ("=================================");
System.out.println ( "after clone, c2.str =" + c2.str);
System.out.println ( "after clone, c2.strBuff =" + c2.strBuff);
)
)
/ * RUN RESULT
before clone, c1.str = initializeStr
before clone, c1.strBuff = initializeStrBuff
=================================
after clone, c1.str = initializeStr
after clone, c1.strBuff = initializeStrBuff change strBuff clone
=================================
after clone, c2.str = initi
after clone, c2.strBuff = initializeStrBuff change strBuff clone
*
* /

Print results can be seen, String type variable seems to have achieved a deep clone, since c2.str change did not affect the c1.str! Is Java the Sring look into the basic data type classes? In actual fact, there is a little trick, the secret lies in c2.str = c2.str.substring (0,5) in this statement! In essence, when the clone is still c1.str and c2.str reference, and they all point to the same String object. However, in the implementation of c2.str = c2.str.substring (0,5) when it acts as generate a new type of String, and then assigned back to the c2.str. This is because String has been written in Sun's engineers had an immutable class (immutable class), in all the functions in the String class can not change their value. Here's a very simple example:
package clone; public class StrTest (public static void main (String [] args) (String str1 = "This is a test for immutable"; String str2 = str1.substring (0,8); System.out.println ( "print str1: "+ str1); System.out.println (" print str2: "+ str2);)) / * RUN RESULT print str1: This is a test for immutable print str2: This is * /
Example, although the str1 call substring () method, but the value of str1, and has not changed. A similar, String class in other ways as well. Of course, if the above example we have the most in these two statements
c2.str = c2.str.substring (0,5);
c2.strBuff = c2.strBuff.append ( "change strBuff clone");

Replaced by the following:
c2.str.substring (0,5);
c2.strBuff.append ( "change strBuff clone");

Remove the re-assignment process, c2.str there can not be changed, we also Luxian the trick. However, only in the programming process is called
c2.str.substring (0,5);

Statement has no meaning.
Should know is that in Java all the basic data type has a corresponding category, such as Integer class corresponds to int type, Double class corresponding to double type, etc., these classes are also the same as with the String class, are the class can not be changed . In other words, the class of all of these methods are can not change the value of its own. This has also allowed us to compile when the class has a clone more choices. We also can not change your own class compiled classes.
  • del.icio.us
  • StumbleUpon
  • Digg
  • TwitThis
  • Mixx
  • Technorati
  • Facebook
  • NewsVine
  • Reddit
  • Google
  • LinkedIn
  • YahooMyWeb

Related Posts of JAVA in a pointer, the reference and the object's clone (switched from IBM)

  • jboss ejb3 Message Driven Bean

    Super Medium ejb hate. . . . . . . . . . . . . . . . . . . ================================================ To configure a Message Driven Bean in a different application server parameters are not the same. Currently only passed the test jboss. Message Dri

  • Based on Spring's Hibernate Search full-text search function of sample

    Database: Oracle 9i JDBC Driver: OJDBC14 Development Environment: Eclipse-JEE Spring version: Spring 2.0.6 Hibernate version: Hibernate Core 3.2.5/Hibernate Annotation 3.3.0/Hibernate Validator 3.0.0/Hibernate Search 3.0.0 Beta4 / / jdbc.properties (JDBC

  • hibernate using c3p0 connection pooling

    Private http://www.lifevv.com/tenyo/doc/20070605102040991.html c3p0 for open source's JDBC connection pool, with the release hibernate. This article describes how to use the hibernate configuration in c3p0. c3p0 connection pool configuration is v ...

  • Hibernate configuration parameters hibernate.hbm2ddl.auto

    Hibernate in the configuration file: <properties> <property name="hibernate.hbm2ddl.auto" value="create" /> </ properties> Parameter Description: validate load hibernate, the authentication to create a database t ...

  • In the servlet use Bean

    According to Sun's definition, JavaBean is a reusable software components. In fact JavaBean is a Java class, through the package into a property and methods of treatment of a function or a business object, referred to as bean. Because JavaBean is ...

  • hibernate generic generic DAO

    package org.lzpeng.dao; import java.io.Serializable; import java.util.List; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.criterion.Criterion; import org.springside.modules.orm.hibernate.Page; /** * * @version 2009-1-10 *

  • First Hibernate Example

    Curd a simple example. Source does not contain the dependent libraries, or playing too much of the package. PO object Note: One must have the default constructor 2 non-final modified. Otherwise useless lazy loading. UserDAOImpl category code, and other co

  • Struts2 + hibernate + spring problem user log in

    dao layer services layer action jsp <tr> <td align="center"> <b> user name: </ b> </ td> <td> <s: textfield name = "czyNumber" cssClass = "textstyle" theme = "simple" size = &q

  • Hibernate secondary cache

    Hibernate cache: 2-bit cache, also known as process-level cache or SessionFactory level cache, secondary cache can be shared by all of the session Cache configuration and the use of: Will echcache.xml (the document code in hibernate package directory ...

blog comments powered by Disqus
Recent
Recent Entries
Tag Cloud
Random Entries