This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I copy an object in Java?
How can I initialize an object (say A) in java and set its initial member values equal to a second object (say B). After initialization I want to modify the members of A without modifying the members of B. So at initialization of A I only want to copy the data of B. How is this done in a nice way??
You could implement and use clone
MyClass b = new MyClass();
MyClass a = b.clone();
Note: some classes are not Cloneable, or have broken implementations. e.g. only have a shallow copy when they should be a deep copy.
If the class is Serializable you can serialize it and deserialize it in memory. Not exactly nice but it works.
Or you could create your own "copy" constructor.
One possible solution for that would be implement clone method on your class and use clone as follows:
MyClass a = new MyClass();
MyClass b = a;
You will notice that clone() isn't really a public method, so your will need to expose it. Additionally you need to tell Java that your object is Cloneable (this is done making your class implement Cloneable). The following code ilustrate it:
public class MyClass implements Cloneable {
#Override
protected MyClass clone() throws CloneNotSupportedException {
return (MyClass)super.clone();
}
}
That all depends on the type of the members. I'll give an Example:
class A
{
public float value;
public int[] anArray;
public A(B b)
{
//primitive may be assigned directly.
this.value = b.value;
// other types different approaches:
//copy the contents of the array
this.anArray = new int[b.anArray.length];
System.arraycopy(b.anArray, 0, this.anArray, 0, b.anArray.length);
}
}
class B
{
float value;
int[] anArray;
public B(int size)
{
this.value = 3f;
this.anArray = new int[size];
for (int i = size - 1; i >= 0; i--)
{
this.anArray[i] = i * 10;
}
}
}
B b = new B(5);
A a = new A(b);
Cloning is a straightforward option for copying. If you ever want to do something where you need more control, create your own method that performs your copy exactly how you need it:
public MyType copy()
{
MyType a = new MyType();
// Initialize how you need to here, use the object this was called from if you'd like
a.property = this.property;
// etc.
return a;
}
This gives you more direct control, but takes more time to code. If clone will suit your purposes, stick to that.
EDIT: I am going to give an example based on your comments on this answer.
Let us assume we have the following types:
TypeA: has the following member variables
int number = 5; // Default value built in by constructor.
int letter = 'x'; // Value is 'a' when constructed but has been changed.
ArrayList<TypeB> list = {b1, b2, b3} // All are initialized.
TypeB: has the following member variables
double decimal = 5.32
TypeC someObject = ...
TypeC: has some stuff, but we are going to ignore it.
Now, When we want to copy TypeA, we must do the following:
Copy over the number and character directly as they are value types.
Copy over a reference to the ArrayList which contains a reference to some TypeBs.
Luckily those are easy steps.
int copyNumber = this.number;
char copyChar = this.letter;
ArrayList<TypeB> copyList = this.list;
return new TypeA(copyNumber, copyChar, copyList);
Now that assumes a particular constructor that takes those three arguments, but hopefully you get the idea.
It would get tricky if you wanted to just get values, not references to all of the TypeBs in the ArrayList. You would have to loop through the ArrayList and create new TypeBs that copied all of ITS values (double and TypeC objects as either references or values...)
In short, what you want is an easier copy to perform. Simple assignment operators copy values with primitive types and references with Objects.
Related
What is the purpose of this code?
public Fraction(Fraction other) {
num = other.num;
denom = other.denom;
}
If you have a constructor like this:
public Fraction(int n, int d) {
num = n;
denom = d;
}
Why do you have to initialize other.num to num and other.denom to denom. What is with the syntax of the copy constructor? What is the purpose?
It is much more convenient to use.
If you have a simple constructor like:
public Fraction(int n, int d) {
num = n;
denom = d;
}
You can copy the instance original with following code:
Fraction copy = new Fraction(original.num, original.denom);
When using a copy constructor you perform following call:
Fraction copy = new Fraction(original);
In case you have many parameters this can be much more convenient. What is when you change the arguments of your constructor or your object? Without a copy constructor you have to change all such calls.
Noteworthy fact from M. Prokhorov's comment:
There is no special syntax for copy constructors, they are just
logical style of implementing a parameterized constructor.
If you were to simply type
public Fraction(Fraction other) {
}
Java isn't simply going to guess that you want to copy the values of other into the new object. Java does not automatically initialize your variables for you like that. For it to be a copy constructor, you still have to manually type out the code that copies the fields from other to the object you are creating. Like this:
public Fraction(Fraction other) {
num = other.num;
denom = other.denom;
}
The constructor creates a new Fraction but it is the code you type inside it that manually performs the "copying" that makes it a "copy constructor" and allows you to do
Fraction a = Fraction(4, 20);
Fraction b = new Fraction(a);
// b has the same values as a but is a different object
Of course, if you already have another constructor, a shorter way to make a copy constructor is
public Fraction(int n, int d) {
num = n;
denom = d;
}
public Fraction(Fraction other) {
this(other.num, other.denom);
}
There are 2 good reasons for using a copy constructor instead of the constructor passing all parameters :
when we have a complex object with many attributes it is convenient to use the copy constructor
if we add an attribute to the existing class, then we can just change the copy constructor to take this new attribute into account instead of changing every occurrence of the other constructor
If you have an instance of the Fraction object like:
Fraction fr = new Fraction(1, 2); //represents 1/2
Of course you can copy it by just assigning it to a new variable:
Fraction copy = fr;
But now, both fr and copy point to the same object (same location in memory). If, for some reason, copy changes to 1/3, fr will change too.
Sometimes you want a completely fresh copy of your original object. That is where it is really handy to write:
Fraction copy = new Fraction(fr);
Now you can independently manipulate copy and fr without worrying about unwanted changes in any of them.
You can read this tutorial to gain more in-depth information on the subject.
public class foo {
private int a[];
private int b;
public foo(){
a = new int[] {1,2};
b= 3;
}
public int[] getA(){
return this.a;
}
public int getB(){
return this.b;
}
I noticed that it's possible to change a value of A by accessing the object like this:
foo f = new foo();
f.getA()[0] = 5; // f.a[0] changes to 5
but it isn't possible to do something like:
f.getB = 5; // gives error
f.getA() = new int[]{2,3}; //gives error
can someone explain me how this works, and how to prevent the user from changing the value of an array cell?
Thanks in advance.
In Java, array is a reference type, which means that the value of an array expression is a reference to the actual array.
The return value of getA() is, therefore, a reference to the private array inside your object. This breaks encapsulation: you give access to your object's internals.
You can avoid this by either returning a reference to a copy of your internal array, or by providing a different API which only returns individual elements, say a method getA(int index).
f.get(A) returns a reference to an array. You can access that array the way you access any array, and assign values to its elements with f.get(A)[i]=... (though it makes more sense to store the returned array in a variable, which would let you access that array multiple times, without having to call f.get(A) each time).
You can't, however, assign anything f.get(A) via f.get(A)=.., since a method call is not a valid left side of an assignment operator. For all you know, a call to f.get(A) may generate a new array that is not referred to by a member of the foo class, so assigning f.get(A)= new int[5]; would make no sense, since there would be no variable in which to store the new array.
The same explanation applies to f.getB() = 5;.
Instead of giving away the array, to allow the caller to do what they like with it you can use an indexed getter
public int getA(int n){
return this.a[n];
}
public void setA(int n, int x) {
this.a[n] = x;
}
Now, the caller has no access to the array and cannot change it without you knowing.
1. Definitions
- The class Object has a protected method clone which performs a shallow copy of the object, this method should be overridden in any class cloneable.
- There is a very particular Cloneable interface, when it's implemented in a class, it does not require the redefinition of the clone method.
- The declaration: class X implements Cloneable
mentioned that class X can make a deep copy by calling the clone method which is the clone method of Object class or method provided by X.
1.1 I want to know if the definitions and rules described above are correct or not?
2. Example
When i want to make a deep copy of an object of a class, i used the following example:
class A implements Cloneable
{
int valueA = 10;
B b = new B();
public A clone()
{
A result = new A();
try
{
result = (A)(super.clone());
}
catch (CloneNotSupportedException e)
{
}
return result;
}
}
class B
{
int valueB = 20;
}
public class Test
{
public static void main(String[] args)
{
A a = new A();
A a1 = a.clone();
a1.valueA = 12;
a1.b.valueB = 64;
System.out.println("a.valueA = " + a.valueA);
System.out.println("a1.valueA = " + a1.valueA);
System.out.println("a.b.valueB = " + a.b.valueB);
System.out.println("a1.b.valueB = " + a1.b.valueB);
}
}
The output is :
a.valueA = 10
a1.valueA = 12
a.b.valueB = 64
a1.b.valueB = 64
I see that the deep copy is not well done because the valueB of object field b in object a is modified.
2.1 Why i get this ? is it due to my lack of comprehension of how should i make deep copy ? or the example is not enough ?
2.2 Can anyone give two correct examples of how should i make correctly shallow and deep copy ?
If you want to make a deep copy, then you need to also clone B when you clone A (or create another B instance using, for example, a copy constructor). Object.clone() simply creates a new instance of the objects containing references to the same objects as the object being cloned. It's a shallow copy. There is no way to correctly make a generic deep copy, simply because it often doesn't make sense:
cloning a String, for example, is useless since Strings are immutable
cloning a Socket, for example, makes no sense as a Socket is not clonable, since it represents an active side of a TCP connection, that can't be duplicated.
You should generally avoid using Cloneable. Prefer copy constructors instead. And favor immutability rather than deep copies.
Have a class including 30+ member variables, need to pass it to a function and then return it from the function after processing. but this function only accept fundamental data types, such as string, int.
I want to convert these member variables into an object array, pass it to the function, then convert back.
have a easy way to do these except converting one bye one?
source code like this:
class A{
int member1;
string member2;
int member3;
//other member variables
A(){
//source code
}
A(Object[] objs){
//assign objects in "objs" array to member variables
}
Object[] asArray(){
//put member variables into a object array
}
};
class B extends SuperB{
//can't modify SuperB, only can inherit it
//only accept fundamental data types, such as string, int
public Object[] run(Object... args){
A a = new A(args);
//processing
return a.asArray();
}
}
public static void main(String[] args){
A a = new A();
//other source code
Processor p = new Processor();
object[] updatedObjs = b.call("B", a.asArray());
a = new A(updatedObjs);
//other source code
};
To do what you are asking you need to do a little bit of java reflection. Loop through all the fields and add them to an array.
If you are not sure what is java reflection:
http://docs.oracle.com/javase/tutorial/reflect/
Otherwise, if you dont want to go through spinning out something on your own, you could use the immensely powerful and popular common beanutils
http://commons.apache.org/proper/commons-beanutils/
If you use the dynabean feature, you could do all this in a few lines of code:
WrapDynaBean wrapDynaBean=new WrapDynaBean(new A());
DynaProperty[] dynaProperties = wrapDynaBean.getDynaClass().getDynaProperties();
List<Object> objects=new ArrayList<>();
for (DynaProperty dynaProperty : dynaProperties) {
System.out.println(dynaProperty.getName()+" = "+wrapDynaBean.get(dynaProperty.getName()));
objects.add(wrapDynaBean.get(dynaProperty.getName()));
}
Object[] theArrayYouWant=objects.toArray(new Object[objects.size()]);
I am making a copy of my object by using clone() method. But when there is modification in the copy the original object is also modified. I have tried to replicate my issue in the following example. Here are 2 classes ClassA and ClassB.
public class ClassB implements Cloneable
{
int num = 0;
byte[] bit = new byte[1];
//Getters and setters have been removed due to space constraint
public Object clone()
{
try
{
ClassB obj = (ClassB)super.clone();
obj.setNum(this.num);
obj.setBit(this.bit);
return obj;
} catch (CloneNotSupportedException e) {
return null; }
}
}
//Here is ClassA whioch contains the main method and uses clone
public class ClassA {
public void cloneMethod(){
ClassB objB = new ClassB();
objB.bit[0] = (byte)0x8;
objB.setNum(5);
ClassB objCopy = null;
objCopy = (ClassB) objB.clone();
if(objCopy.bit[0] != (byte)0x0)
{
objCopy.bit[0] = 0;
}
System.out.println(objB.bit[0]); //At this point the original object value is also modified.
}
public static void main(String args[])
{
ClassA a = new ClassA();
a.cloneMethod();
}
}
Now how to retain the original object value? I know clone has certain disadvantages. I have tried with new key word also but it doesnt help.Please suggest.
in my original code I have to use the original object bit value later for some more calculation and the copy object bit value will be 0.
Thanks.
Don't set bit to the same byte[] as the original object, instead clone it as well:
obj.bit = this.bit.clone();
Also, you don't need to set num, because that will already be set correctly on the object returned by super.clone().
obj.setNum(this.num);
obj.setBit(this.bit);
These two lines of code are (a) redundant and (b) wrong. If you just want the original field values in the clone you don't need this at all, because super.clone() has already done it for you. If your aim is to return an independently-valued object. As bit[] is an array, i.e. an Object, you should clone it too.
You are not cloning your bit array.