Java: Deep Copy Constructor [duplicate] - java

Consider the code below:
DummyBean dum = new DummyBean();
dum.setDummy("foo");
System.out.println(dum.getDummy()); // prints 'foo'
DummyBean dumtwo = dum;
System.out.println(dumtwo.getDummy()); // prints 'foo'
dum.setDummy("bar");
System.out.println(dumtwo.getDummy()); // prints 'bar' but it should print 'foo'
So, I want to copy the dum to dumtwo and change dum without affecting the dumtwo. But the code above is not doing that. When I change something in dum, the same change is happening in dumtwo also.
I guess, when I say dumtwo = dum, Java copies the reference only. So, is there any way to create a fresh copy of dum and assign it to dumtwo?

Create a copy constructor:
class DummyBean {
private String dummy;
public DummyBean(DummyBean another) {
this.dummy = another.dummy; // you can access
}
}
Every object has also a clone method which can be used to copy the object, but don't use it. It's way too easy to create a class and do improper clone method. If you are going to do that, read at least what Joshua Bloch has to say about it in Effective Java.

Basic: Object Copying in Java.
Let us Assume an object- obj1, that contains two objects, containedObj1 and containedObj2.
shallow copying:
shallow copying creates a new instance of the same class and copies all the fields to the new instance and returns it. Object class provides a clone method and provides support for the shallow copying.
Deep copying:
A deep copy occurs when an object is copied along with the objects to which it refers. Below image shows obj1 after a deep copy has been performed on it. Not only has obj1 been copied, but the objects contained within it have been copied as well. We can use Java Object Serialization to make a deep copy. Unfortunately, this approach has some problems too(detailed examples).
Possible Problems:
clone is tricky to implement correctly.
It's better to use Defensive copying, copy constructors(as #egaga reply) or static factory methods.
If you have an object, that you know has a public clone() method, but you don’t know the type of the object at compile time, then you have problem. Java has an interface called Cloneable. In practice, we should implement this interface if we want to make an object Cloneable. Object.clone is protected, so we must override it with a public method in order for it to be accessible.
Another problem arises when we try deep copying of a complex object. Assume that the clone() method of all member object variables also does deep copy, this is too risky of an assumption. You must control the code in all classes.
For example org.apache.commons.lang.SerializationUtils will have method for Deep clone using serialization(Source). If we need to clone Bean then there are couple of utility methods in org.apache.commons.beanutils (Source).
cloneBean will Clone a bean based on the available property getters and setters, even if the bean class itself does not implement Cloneable.
copyProperties will Copy property values from the origin bean to the destination bean for all cases where the property names are the same.

In the package import org.apache.commons.lang.SerializationUtils; there is a method:
SerializationUtils.clone(Object);
Example:
this.myObjectCloned = SerializationUtils.clone(this.object);

Just follow as below:
public class Deletable implements Cloneable{
private String str;
public Deletable(){
}
public void setStr(String str){
this.str = str;
}
public void display(){
System.out.println("The String is "+str);
}
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
and wherever you want to get another object, simple perform cloning.
e.g:
Deletable del = new Deletable();
Deletable delTemp = (Deletable ) del.clone(); // this line will return you an independent
// object, the changes made to this object will
// not be reflected to other object

Why is there no answer for using Reflection API?
private static Object cloneObject(Object obj){
try{
Object clone = obj.getClass().newInstance();
for (Field field : obj.getClass().getDeclaredFields()) {
field.setAccessible(true);
field.set(clone, field.get(obj));
}
return clone;
}catch(Exception e){
return null;
}
}
It's really simple.
EDIT: Include child object via recursion
private static Object cloneObject(Object obj){
try{
Object clone = obj.getClass().newInstance();
for (Field field : obj.getClass().getDeclaredFields()) {
field.setAccessible(true);
if(field.get(obj) == null || Modifier.isFinal(field.getModifiers())){
continue;
}
if(field.getType().isPrimitive() || field.getType().equals(String.class)
|| field.getType().getSuperclass().equals(Number.class)
|| field.getType().equals(Boolean.class)){
field.set(clone, field.get(obj));
}else{
Object childObj = field.get(obj);
if(childObj == obj){
field.set(clone, clone);
}else{
field.set(clone, cloneObject(field.get(obj)));
}
}
}
return clone;
}catch(Exception e){
return null;
}
}

I use Google's JSON library to serialize it then create a new instance of the serialized object. It does deep copy with a few restrictions:
there can't be any recursive references
it won't copy arrays of disparate types
arrays and lists should be typed or it won't find the class to instantiate
you may need to encapsulate strings in a class you declare yourself
I also use this class to save user preferences, windows and whatnot to be reloaded at runtime. It is very easy to use and effective.
import com.google.gson.*;
public class SerialUtils {
//___________________________________________________________________________________
public static String serializeObject(Object o) {
Gson gson = new Gson();
String serializedObject = gson.toJson(o);
return serializedObject;
}
//___________________________________________________________________________________
public static Object unserializeObject(String s, Object o){
Gson gson = new Gson();
Object object = gson.fromJson(s, o.getClass());
return object;
}
//___________________________________________________________________________________
public static Object cloneObject(Object o){
String s = serializeObject(o);
Object object = unserializeObject(s,o);
return object;
}
}

Yes, you are just making a reference to the object. You can clone the object if it implements Cloneable.
Check out this wiki article about copying objects.
Refer here: Object copying

Add Cloneable and below code to your class
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
Use this clonedObject = (YourClass) yourClassObject.clone();

Deep Cloning is your answer, which requires implementing the Cloneable interface and overriding the clone() method.
public class DummyBean implements Cloneable {
private String dummy;
public void setDummy(String dummy) {
this.dummy = dummy;
}
public String getDummy() {
return dummy;
}
#Override
public Object clone() throws CloneNotSupportedException {
DummyBean cloned = (DummyBean)super.clone();
cloned.setDummy(cloned.getDummy());
// the above is applicable in case of primitive member types like String
// however, in case of non primitive types
// cloned.setNonPrimitiveType(cloned.getNonPrimitiveType().clone());
return cloned;
}
}
You will call it like this
DummyBean dumtwo = dum.clone();

This works too. Assuming model
class UserAccount{
public int id;
public String name;
}
First add
compile 'com.google.code.gson:gson:2.8.1' to your app>gradle & sync. Then
Gson gson = new Gson();
updateUser = gson.fromJson(gson.toJson(mUser),UserAccount.class);
You can exclude using a field by using transient keyword after access modifier.
Note: This is bad practice. Also don't recommend to use Cloneable or JavaSerialization It's slow and broken. Write copy constructor for best performance ref.
Something like
class UserAccount{
public int id;
public String name;
//empty constructor
public UserAccount(){}
//parameterize constructor
public UserAccount(int id, String name) {
this.id = id;
this.name = name;
}
//copy constructor
public UserAccount(UserAccount in){
this(in.id,in.name);
}
}
Test stats of 90000 iteration:
Line UserAccount clone = gson.fromJson(gson.toJson(aO), UserAccount.class); takes 808ms
Line UserAccount clone = new UserAccount(aO); takes less than 1ms
Conclusion: Use gson if your boss is crazy and you prefer speed. Use second copy constructor if you prefer quality.
You can also use copy constructor code generator plugin in Android Studio.

Here's a decent explanation of clone() if you end up needing it...
Here: clone (Java method)

Use a deep cloning utility:
SomeObjectType copy = new Cloner().deepClone(someObject);
This will deep copy any java object, check it out at https://github.com/kostaskougios/cloning

Alternative to egaga's constructor method of copy. You probably already have a POJO, so just add another method copy() which returns a copy of the initialized object.
class DummyBean {
private String dummyStr;
private int dummyInt;
public DummyBean(String dummyStr, int dummyInt) {
this.dummyStr = dummyStr;
this.dummyInt = dummyInt;
}
public DummyBean copy() {
return new DummyBean(dummyStr, dummyInt);
}
//... Getters & Setters
}
If you already have a DummyBean and want a copy:
DummyBean bean1 = new DummyBean("peet", 2);
DummyBean bean2 = bean1.copy(); // <-- Create copy of bean1
System.out.println("bean1: " + bean1.getDummyStr() + " " + bean1.getDummyInt());
System.out.println("bean2: " + bean2.getDummyStr() + " " + bean2.getDummyInt());
//Change bean1
bean1.setDummyStr("koos");
bean1.setDummyInt(88);
System.out.println("bean1: " + bean1.getDummyStr() + " " + bean1.getDummyInt());
System.out.println("bean2: " + bean2.getDummyStr() + " " + bean2.getDummyInt());
Output:
bean1: peet 2
bean2: peet 2
bean1: koos 88
bean2: peet 2
But both works well, it is ultimately up to you...

To do that you have to clone the object in some way. Although Java has a cloning mechanism, don't use it if you don't have to. Create a copy method that does the copy work for you, and then do:
dumtwo = dum.copy();
Here is some more advice on different techniques for accomplishing a copy.

Pass the object that you want to copy and get the object you want:
private Object copyObject(Object objSource) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(objSource);
oos.flush();
oos.close();
bos.close();
byte[] byteData = bos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(byteData);
try {
objDest = new ObjectInputStream(bais).readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return objDest;
}
Now parse the objDest to desired object.
Happy Coding!

Use gson for duplicating an object.
public static <T>T copyObject(Object object){
Gson gson = new Gson();
JsonObject jsonObject = gson.toJsonTree(object).getAsJsonObject();
return gson.fromJson(jsonObject,(Type) object.getClass());
}
Assume I have an object person.So
Person copyPerson = copyObject(person);
Note: The performance is much slower.

Other than explicitly copying, another approach is to make the object immutable (no set or other mutator methods). In this way the question never arises. Immutability becomes more difficult with larger objects, but that other side of that is that it pushes you in the direction of splitting into coherent small objects and composites.

class DB {
private String dummy;
public DB(DB one) {
this.dummy = one.dummy;
}
}

You can deep copy automatically with XStream, from http://x-stream.github.io/:
XStream is a simple library to serialize objects to XML and back
again.
Add it to your project (if using maven)
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.3.1</version>
</dependency>
Then
DummyBean dum = new DummyBean();
dum.setDummy("foo");
DummyBean dumCopy = (DummyBean) XSTREAM.fromXML(XSTREAM.toXML(dum));
With this you have a copy without the need to implement any cloning interface.

public class MyClass implements Cloneable {
private boolean myField= false;
// and other fields or objects
public MyClass (){}
#Override
public MyClass clone() throws CloneNotSupportedException {
try
{
MyClass clonedMyClass = (MyClass)super.clone();
// if you have custom object, then you need create a new one in here
return clonedMyClass ;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return new MyClass();
}
}
}
and in your code:
MyClass myClass = new MyClass();
// do some work with this object
MyClass clonedMyClass = myClass.clone();

You can try to implement Cloneable and use the clone() method; however, if you use the clone method you should - by standard - ALWAYS override Object's public Object clone() method.

If you can add an annotation to the source file, an annotation processor or code generator like this one can be used.
import net.zerobuilder.BeanBuilder
#BeanBuilder
public class DummyBean {
// bean stuff
}
A class DummyBeanBuilders will be generates, which has a static method dummyBeanUpdater to create shallow copies, the same way as you would do it manually.
DummyBean bean = new DummyBean();
// Call some setters ...
// Now make a copy
DummyBean copy = DummyBeanBuilders.dummyBeanUpdater(bean).done();

Using Kotlin extension function
fun <T : Any?> T.duplicate(): T? {
var copyObject: T? = null
try {
val byteArrayOutputStream = ByteArrayOutputStream()
val objectOutputStream = ObjectOutputStream(byteArrayOutputStream)
objectOutputStream.writeObject(this)
objectOutputStream.flush()
objectOutputStream.close()
byteArrayOutputStream.close()
val byteData = byteArrayOutputStream.toByteArray()
val byteArrayInputStream = ByteArrayInputStream(byteData)
try {
copyObject = ObjectInputStream(byteArrayInputStream).readObject() as T
} catch (e: ClassNotFoundException) {
e.printStackTrace()
}
} catch (e: IOException) {
e.printStackTrace()
}
return copyObject
}
Use case
var object = Any()
var duplicateObject = object.duplicate()
Java
<T extends Object> T copyObject(T sourceObject) {
T copyObject = null;
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(sourceObject);
objectOutputStream.flush();
objectOutputStream.close();
byteArrayOutputStream.close();
byte[] byteData = byteArrayOutputStream.toByteArray();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteData);
try {
copyObject = (T) new ObjectInputStream(byteArrayInputStream).readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return copyObject;
}
Use case
Object object = new Object();
Object duplicateObject = copyObject(object);
==============================================
Kotlin Update
If you use data class then you will have copy method that copies the Kotlin data class. Cool thing is you could also pass some values to modify the object with new copy. I would recommend this way.
Example:
//class
data class TestModel(val title: String, var subtitle: String)
Use case
val testClass = TestModel("Test title", "Test subtitle")
val newInstance = testClass.copy(subtitle = "new subtitle for copy instance")

Related

Deep clone by collecting the fields

I have classes which aim to contain many attributes of different types. I would want to automatically deep clone all of them rather than writing an instruction for each of them:
class AttributesContainer implements Cloneable {
Type1 a1 = new Type1(...), a2 = new Type1(...);
Type2 b1 = new Type2(...);
...
public AttributesContainer clone() {
AttributesContainer ac = (AttributesContainer) super.clone();
// Regroup that like using a loop
ac.a1 = a1.clone();
ac.a2 = a2.clone();
ac.b1 = b1.clone();
...
return ac;
}
}
I have thought about adding the fields in a table each time but I could not change the reference of the fields:
class ContainerAbstract implements Cloneable {
public <T> T add(T t) {
// adds the reference into a list
return t;
}
public ContainerAbstract clone() {
ContainerAbstract ca = (ContainerAbstract) super.clone();
// copy the attributes
return ca;
}
}
class AttributesContainer extends ContainerAbstract implements Cloneable {
Type1 a1 = add(new Type1(...)), a2 = add(new Type1(...));
Type2 b1 = add(new Type2(...));
...
public AttributesContainer clone() {
AttributesContainer ac = (AttributesContainer) super.clone();
return ac;
}
}
I have also thought that I could return a wrapper in the add() method but it would introduce an extra method get() to call each time I want to access an attribute:
AttributesContainer ac = new AttributesContainer();
ac.get()...;
It there a way to change the fields to there source, like we could achieve that in C using a pointer?
NB: I already checked Copy fields between similar classes in java, How do you make a deep copy of an object in Java? and http://www.java2s.com/Tutorial/Java/0125__Reflection/Returnalistofallfieldswhateveraccessstatusandonwhateversuperclasstheyweredefinedthatcanbefoundonthisclass.htm.
EDIT: One of the reasons I don't use the serialization is that in fact, I have a final property for which I just want a fresh new instance.
I thought about making it transient and then giving it a new object but I can't, since it is final:
class A {
private Double d = new Double(2);
public final transient B b = new B();
public A copy() {
A a = (A) DeepCopy.copy(this);
a.b = new B(); // Error, b is final
return a;
}
}
Always check when articles are written (or questions are asked/answered), otherwise you'll get plenty of misconceptions. The text I quoted in my comment is in the bottom of the page. If you don't see it, use the "Find in page" functionality of your browser.
Serializing and deserializing final fields is not a problem either. You can't write this: a.b = new B(); // Error, b is final, but you don't need to. Serialization is implemented on the JVM level and it can perform plenty of tricks, such as creating objects without calling any constructors.
Finally, the only answer I found without needing to change a final attribute is to change in the class DeepCopy in http://javatechniques.com/blog/faster-deep-copies-of-java-objects/ the ObjectOutputStream method to replace attributes of the class Type with new ones.
ObjectOutputStream out = new ObjectOutputStream(fbos) {
{
enableReplaceObject(true);
}
#Override
protected Object replaceObject(Object arg0) throws IOException {
// TODO Auto-generated method stub
if(arg0 instanceof Type) {
for(Constructor<?> constructor : arg0.getClass().getConstructors()) {
Class<?>[] parameterTypes = constructor.getParameterTypes();
if(parameterTypes.length == 0 /* Number of arguments in the constructor of new Type(...) */)
try {
return constructor.newInstance(/* Arguments to the constructor */);
} catch (InstantiationException | IllegalAccessException
| IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
}
try {
throw new Exception("The constructor needed to create a new Type was not found.");
} catch(Exception e) {
e.printStackTrace();
}
return null;
} else {
return super.replaceObject(arg0);
}
}
};
out.writeObject(orig);
out.flush();
out.close();

Making a copy of an object array and not change values of original array [duplicate]

Consider the code below:
DummyBean dum = new DummyBean();
dum.setDummy("foo");
System.out.println(dum.getDummy()); // prints 'foo'
DummyBean dumtwo = dum;
System.out.println(dumtwo.getDummy()); // prints 'foo'
dum.setDummy("bar");
System.out.println(dumtwo.getDummy()); // prints 'bar' but it should print 'foo'
So, I want to copy the dum to dumtwo and change dum without affecting the dumtwo. But the code above is not doing that. When I change something in dum, the same change is happening in dumtwo also.
I guess, when I say dumtwo = dum, Java copies the reference only. So, is there any way to create a fresh copy of dum and assign it to dumtwo?
Create a copy constructor:
class DummyBean {
private String dummy;
public DummyBean(DummyBean another) {
this.dummy = another.dummy; // you can access
}
}
Every object has also a clone method which can be used to copy the object, but don't use it. It's way too easy to create a class and do improper clone method. If you are going to do that, read at least what Joshua Bloch has to say about it in Effective Java.
Basic: Object Copying in Java.
Let us Assume an object- obj1, that contains two objects, containedObj1 and containedObj2.
shallow copying:
shallow copying creates a new instance of the same class and copies all the fields to the new instance and returns it. Object class provides a clone method and provides support for the shallow copying.
Deep copying:
A deep copy occurs when an object is copied along with the objects to which it refers. Below image shows obj1 after a deep copy has been performed on it. Not only has obj1 been copied, but the objects contained within it have been copied as well. We can use Java Object Serialization to make a deep copy. Unfortunately, this approach has some problems too(detailed examples).
Possible Problems:
clone is tricky to implement correctly.
It's better to use Defensive copying, copy constructors(as #egaga reply) or static factory methods.
If you have an object, that you know has a public clone() method, but you don’t know the type of the object at compile time, then you have problem. Java has an interface called Cloneable. In practice, we should implement this interface if we want to make an object Cloneable. Object.clone is protected, so we must override it with a public method in order for it to be accessible.
Another problem arises when we try deep copying of a complex object. Assume that the clone() method of all member object variables also does deep copy, this is too risky of an assumption. You must control the code in all classes.
For example org.apache.commons.lang.SerializationUtils will have method for Deep clone using serialization(Source). If we need to clone Bean then there are couple of utility methods in org.apache.commons.beanutils (Source).
cloneBean will Clone a bean based on the available property getters and setters, even if the bean class itself does not implement Cloneable.
copyProperties will Copy property values from the origin bean to the destination bean for all cases where the property names are the same.
In the package import org.apache.commons.lang.SerializationUtils; there is a method:
SerializationUtils.clone(Object);
Example:
this.myObjectCloned = SerializationUtils.clone(this.object);
Just follow as below:
public class Deletable implements Cloneable{
private String str;
public Deletable(){
}
public void setStr(String str){
this.str = str;
}
public void display(){
System.out.println("The String is "+str);
}
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
and wherever you want to get another object, simple perform cloning.
e.g:
Deletable del = new Deletable();
Deletable delTemp = (Deletable ) del.clone(); // this line will return you an independent
// object, the changes made to this object will
// not be reflected to other object
Why is there no answer for using Reflection API?
private static Object cloneObject(Object obj){
try{
Object clone = obj.getClass().newInstance();
for (Field field : obj.getClass().getDeclaredFields()) {
field.setAccessible(true);
field.set(clone, field.get(obj));
}
return clone;
}catch(Exception e){
return null;
}
}
It's really simple.
EDIT: Include child object via recursion
private static Object cloneObject(Object obj){
try{
Object clone = obj.getClass().newInstance();
for (Field field : obj.getClass().getDeclaredFields()) {
field.setAccessible(true);
if(field.get(obj) == null || Modifier.isFinal(field.getModifiers())){
continue;
}
if(field.getType().isPrimitive() || field.getType().equals(String.class)
|| field.getType().getSuperclass().equals(Number.class)
|| field.getType().equals(Boolean.class)){
field.set(clone, field.get(obj));
}else{
Object childObj = field.get(obj);
if(childObj == obj){
field.set(clone, clone);
}else{
field.set(clone, cloneObject(field.get(obj)));
}
}
}
return clone;
}catch(Exception e){
return null;
}
}
I use Google's JSON library to serialize it then create a new instance of the serialized object. It does deep copy with a few restrictions:
there can't be any recursive references
it won't copy arrays of disparate types
arrays and lists should be typed or it won't find the class to instantiate
you may need to encapsulate strings in a class you declare yourself
I also use this class to save user preferences, windows and whatnot to be reloaded at runtime. It is very easy to use and effective.
import com.google.gson.*;
public class SerialUtils {
//___________________________________________________________________________________
public static String serializeObject(Object o) {
Gson gson = new Gson();
String serializedObject = gson.toJson(o);
return serializedObject;
}
//___________________________________________________________________________________
public static Object unserializeObject(String s, Object o){
Gson gson = new Gson();
Object object = gson.fromJson(s, o.getClass());
return object;
}
//___________________________________________________________________________________
public static Object cloneObject(Object o){
String s = serializeObject(o);
Object object = unserializeObject(s,o);
return object;
}
}
Yes, you are just making a reference to the object. You can clone the object if it implements Cloneable.
Check out this wiki article about copying objects.
Refer here: Object copying
Add Cloneable and below code to your class
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
Use this clonedObject = (YourClass) yourClassObject.clone();
Deep Cloning is your answer, which requires implementing the Cloneable interface and overriding the clone() method.
public class DummyBean implements Cloneable {
private String dummy;
public void setDummy(String dummy) {
this.dummy = dummy;
}
public String getDummy() {
return dummy;
}
#Override
public Object clone() throws CloneNotSupportedException {
DummyBean cloned = (DummyBean)super.clone();
cloned.setDummy(cloned.getDummy());
// the above is applicable in case of primitive member types like String
// however, in case of non primitive types
// cloned.setNonPrimitiveType(cloned.getNonPrimitiveType().clone());
return cloned;
}
}
You will call it like this
DummyBean dumtwo = dum.clone();
This works too. Assuming model
class UserAccount{
public int id;
public String name;
}
First add
compile 'com.google.code.gson:gson:2.8.1' to your app>gradle & sync. Then
Gson gson = new Gson();
updateUser = gson.fromJson(gson.toJson(mUser),UserAccount.class);
You can exclude using a field by using transient keyword after access modifier.
Note: This is bad practice. Also don't recommend to use Cloneable or JavaSerialization It's slow and broken. Write copy constructor for best performance ref.
Something like
class UserAccount{
public int id;
public String name;
//empty constructor
public UserAccount(){}
//parameterize constructor
public UserAccount(int id, String name) {
this.id = id;
this.name = name;
}
//copy constructor
public UserAccount(UserAccount in){
this(in.id,in.name);
}
}
Test stats of 90000 iteration:
Line UserAccount clone = gson.fromJson(gson.toJson(aO), UserAccount.class); takes 808ms
Line UserAccount clone = new UserAccount(aO); takes less than 1ms
Conclusion: Use gson if your boss is crazy and you prefer speed. Use second copy constructor if you prefer quality.
You can also use copy constructor code generator plugin in Android Studio.
Here's a decent explanation of clone() if you end up needing it...
Here: clone (Java method)
Use a deep cloning utility:
SomeObjectType copy = new Cloner().deepClone(someObject);
This will deep copy any java object, check it out at https://github.com/kostaskougios/cloning
Alternative to egaga's constructor method of copy. You probably already have a POJO, so just add another method copy() which returns a copy of the initialized object.
class DummyBean {
private String dummyStr;
private int dummyInt;
public DummyBean(String dummyStr, int dummyInt) {
this.dummyStr = dummyStr;
this.dummyInt = dummyInt;
}
public DummyBean copy() {
return new DummyBean(dummyStr, dummyInt);
}
//... Getters & Setters
}
If you already have a DummyBean and want a copy:
DummyBean bean1 = new DummyBean("peet", 2);
DummyBean bean2 = bean1.copy(); // <-- Create copy of bean1
System.out.println("bean1: " + bean1.getDummyStr() + " " + bean1.getDummyInt());
System.out.println("bean2: " + bean2.getDummyStr() + " " + bean2.getDummyInt());
//Change bean1
bean1.setDummyStr("koos");
bean1.setDummyInt(88);
System.out.println("bean1: " + bean1.getDummyStr() + " " + bean1.getDummyInt());
System.out.println("bean2: " + bean2.getDummyStr() + " " + bean2.getDummyInt());
Output:
bean1: peet 2
bean2: peet 2
bean1: koos 88
bean2: peet 2
But both works well, it is ultimately up to you...
To do that you have to clone the object in some way. Although Java has a cloning mechanism, don't use it if you don't have to. Create a copy method that does the copy work for you, and then do:
dumtwo = dum.copy();
Here is some more advice on different techniques for accomplishing a copy.
Pass the object that you want to copy and get the object you want:
private Object copyObject(Object objSource) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(objSource);
oos.flush();
oos.close();
bos.close();
byte[] byteData = bos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(byteData);
try {
objDest = new ObjectInputStream(bais).readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return objDest;
}
Now parse the objDest to desired object.
Happy Coding!
Use gson for duplicating an object.
public static <T>T copyObject(Object object){
Gson gson = new Gson();
JsonObject jsonObject = gson.toJsonTree(object).getAsJsonObject();
return gson.fromJson(jsonObject,(Type) object.getClass());
}
Assume I have an object person.So
Person copyPerson = copyObject(person);
Note: The performance is much slower.
Other than explicitly copying, another approach is to make the object immutable (no set or other mutator methods). In this way the question never arises. Immutability becomes more difficult with larger objects, but that other side of that is that it pushes you in the direction of splitting into coherent small objects and composites.
class DB {
private String dummy;
public DB(DB one) {
this.dummy = one.dummy;
}
}
You can deep copy automatically with XStream, from http://x-stream.github.io/:
XStream is a simple library to serialize objects to XML and back
again.
Add it to your project (if using maven)
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.3.1</version>
</dependency>
Then
DummyBean dum = new DummyBean();
dum.setDummy("foo");
DummyBean dumCopy = (DummyBean) XSTREAM.fromXML(XSTREAM.toXML(dum));
With this you have a copy without the need to implement any cloning interface.
public class MyClass implements Cloneable {
private boolean myField= false;
// and other fields or objects
public MyClass (){}
#Override
public MyClass clone() throws CloneNotSupportedException {
try
{
MyClass clonedMyClass = (MyClass)super.clone();
// if you have custom object, then you need create a new one in here
return clonedMyClass ;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return new MyClass();
}
}
}
and in your code:
MyClass myClass = new MyClass();
// do some work with this object
MyClass clonedMyClass = myClass.clone();
You can try to implement Cloneable and use the clone() method; however, if you use the clone method you should - by standard - ALWAYS override Object's public Object clone() method.
If you can add an annotation to the source file, an annotation processor or code generator like this one can be used.
import net.zerobuilder.BeanBuilder
#BeanBuilder
public class DummyBean {
// bean stuff
}
A class DummyBeanBuilders will be generates, which has a static method dummyBeanUpdater to create shallow copies, the same way as you would do it manually.
DummyBean bean = new DummyBean();
// Call some setters ...
// Now make a copy
DummyBean copy = DummyBeanBuilders.dummyBeanUpdater(bean).done();
Using Kotlin extension function
fun <T : Any?> T.duplicate(): T? {
var copyObject: T? = null
try {
val byteArrayOutputStream = ByteArrayOutputStream()
val objectOutputStream = ObjectOutputStream(byteArrayOutputStream)
objectOutputStream.writeObject(this)
objectOutputStream.flush()
objectOutputStream.close()
byteArrayOutputStream.close()
val byteData = byteArrayOutputStream.toByteArray()
val byteArrayInputStream = ByteArrayInputStream(byteData)
try {
copyObject = ObjectInputStream(byteArrayInputStream).readObject() as T
} catch (e: ClassNotFoundException) {
e.printStackTrace()
}
} catch (e: IOException) {
e.printStackTrace()
}
return copyObject
}
Use case
var object = Any()
var duplicateObject = object.duplicate()
Java
<T extends Object> T copyObject(T sourceObject) {
T copyObject = null;
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(sourceObject);
objectOutputStream.flush();
objectOutputStream.close();
byteArrayOutputStream.close();
byte[] byteData = byteArrayOutputStream.toByteArray();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteData);
try {
copyObject = (T) new ObjectInputStream(byteArrayInputStream).readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return copyObject;
}
Use case
Object object = new Object();
Object duplicateObject = copyObject(object);
==============================================
Kotlin Update
If you use data class then you will have copy method that copies the Kotlin data class. Cool thing is you could also pass some values to modify the object with new copy. I would recommend this way.
Example:
//class
data class TestModel(val title: String, var subtitle: String)
Use case
val testClass = TestModel("Test title", "Test subtitle")
val newInstance = testClass.copy(subtitle = "new subtitle for copy instance")

Return object based on input string name in java

I have a requirement wherein I've to write a method which accepts "string" and based on this string i need to return an object of type MyObject. This can be done with using switch case, but how could this be achieved dynamically.
In below case method can be called by giving "myObject1" as string, then this method should return myObject1 object. How could this be done.
public class HelloWorld {
MyObject myObject1 = new MyObject();
MyObject myObject2 = new MyObject();
MyObject myObject3 = new MyObject();
public MyObject getMyObject(String string)
{
return <<myObject1 or 2 or 3 based on string parameter name>>;
}
}
class MyObject {
}
This can be done dynamically via reflection, but it would be highly impractical and unnecessary. You should either use a switch or a Map to associate your string identifiers with your actual objects.
Map<String, MyObject> identifiers = new HashMap<>();
...
identifiers.put("myObject1", myObject1);
identifiers.put("myObject2", myObject2);
identifiers.put("myObject3", myObject3);
...
public MyObject getMyObject(String string) {
return identifiers.get(string);
}
If you really want to do things like this reflection is your friend. You can look up declared fields by name, and then use them to look up an instance variable.
I've modified your example to include a main method that looks up each instance of MyObject and also has a failure case. I've also modified MyObject so you can easily tell which instance has been found.
import java.lang.reflect.Field;
public class Reflection {
MyObject myObject1 = new MyObject("1");
MyObject myObject2 = new MyObject("2");
MyObject myObject3 = new MyObject("3");
public MyObject getMyObject(final String string) {
try {
final Field declaredField = this.getClass()
.getDeclaredField(string);
final Object o = declaredField.get(this);
if (o instanceof MyObject) {
return (MyObject) o;
}
} catch (final Exception e) {
}
return null;
}
class MyObject {
final String name;
public MyObject(final String name) {
this.name = name;
}
#Override
public String toString() {
// TODO Auto-generated method stub
return name;
}
}
public static void main(final String[] args) {
final Reflection r = new Reflection();
System.out.println(r.getMyObject("myObject1"));
System.out.println(r.getMyObject("myObject2"));
System.out.println(r.getMyObject("myObject3"));
System.out.println(r.getMyObject("invalid"));
}
}
There is some useful information about reflection in the Oracle Java documentation.
I would look at implementing a Strategy pattern to do this.
You can use:
Class<?> clazz = Class.forName(className);
Object object = clazz.newInstance();
where className - the fully qualified name of the desired class
see http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html for details

Dynamically calling a class method in java?

Is it possible to dynamically call a method on a class from java?
E.g, lets say I have the reference to a class, e.g either the string: 'com.foo.Bar', or com.foo.Bar.class, or anything else which is needed..). And I have an array / list of strings, e.g [First, Last, Email].
I want to simply loop through this array, and call the method 'validate' + element on the class that I have a reference to. E.g:
MyInterface item = //instantiate the com.foo.Bar class here somehow, I'm not sure how.
item.validateFirst();
item.validateLast();
item.validateEmail();
I want the above lines of code to happen dynamically, so I can change the reference to a different class, and the names in my string list can change, but it will still call the validate + name method on whichever class it has the reference to.
Is that possible?
The simplest approach would be to use reflection
Given...
package com.foo;
public class Bar {
public void validateFirst() {
System.out.println("validateFirst");
}
public void validateLast() {
System.out.println("validateLast");
}
public void validateEmail() {
System.out.println("validateEmail");
}
}
You could use something like...
String methodNames[] = new String[]{"First", "Last", "Email"};
String className = "com.foo.Bar";
try {
Class classRef = Class.forName(className);
Object instance = classRef.newInstance();
for (String methodName : methodNames) {
try {
Method method = classRef.getDeclaredMethod("validate" + methodName);
method.invoke(instance);
} catch (NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
ex.printStackTrace();
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
ex.printStackTrace();
}
To look up the methods and execute them.
You will need to decide the best way to handle errors and what they mean to you, but it wouldn't be a difficult them to expand the idea to a reusable method...
Updated with idea of concept discussed in comments
Given....
public interface Validator {
public boolean isValid(Properties formProperties);
}
We can create one or more...
public class UserRegistrationValidator implements Validator {
public boolean isValid(Properties formProperties) {
boolean isValid = false;
// Required fields...
if (formProperties.containsKey("firstName") && formProperties.containsKey("lastName") && formProperties.containsKey("email")) {
// Further processing, valid each required field...
}
if (isValid) {
// Process optional parameters
}
return isValid;
}
}
Then from our input controller, we can look and valid the required forms
public class FormController ... {
private Map<String, Validator> validators;
public void validForm(String formName, Properties formProperties) {
boolean isValid = false;
Validator validator = validators.get(formName);
if (validator != null) {
isValid = validate.isValid(formProperties);
}
return isValid;
}
}
Of course you need to provide some way to register the Validators and there may be differences based on the backbone framework you are using and the parameters you can use (you don't have to use Properties, but it is basically just a Map<String, String>...)
You can write something like this... it takes name of a class as string as an argument, the method name and its arguments
private static String invoke(String aClass, String aMethod, Class<?>[] params,
Object[] args) throws Exception {
String resp = "";
Class<?> c = Class.forName(aClass);
Method m = c.getDeclaredMethod(aMethod, params);
Object i = c.newInstance();
resp = m.invoke(i, args).toString();
return resp;
}
You can also refer to the oracle tutorial on reflection ... which demonstrates how to call methods
http://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html
It's possible using reflection.
First, you create a new class from the FQN (fully qualified name, which is the class name including the package).
Then you iterate through your elements and invoke the "validate" methods on your item.
Class<?> clazz = Class.forName("com.foo.Bar");
Object item = clazz.newInstance();
for (String element : elements) {
Method method = clazz.getDeclaredMethod("validate" + element);
method.invoke(item);
}
You can use reflection, but my favorite method is to use beanutils, eg:
Bar b1 = //...
BeanUtils.getProperty(b1, "first");
BeanUtils.getProperty(b1, "last");
Note that your class has to conform to javabean convention. You can read more about beanutils on this blog post (disclaimer I'm the blog author)
If you know the name of the class beforehand, use Class.forName(yourClassname)
That way, you can invoke the class, and then, you can invoke its methods.
Yes, using reflection.
Using Class.getDeclaredMethod on your object
Object validator = <your object instance>;
final String[] values = {
"Item1","Item2","Item3"
}
for(final String s : values) {
Method m = validator.getDeclaredMethod("validate" + s,String.class);
try {
Object result = m.invoke(validator, s);
}
catch(ex) {}
}

Re-assign values to new object, deep clone, better solution?

I have an object that contains several fields (ints, Strings, etc) but also a HashMap and an ArrayList. This objects holds parameters used to later build a database query but there are times when I need to re-use all of the exact same parameters for an additional query, except for different items in the ArrayList.
I've noticed that when I change what's in the array list, it always changes the original object. I've figured out how to make a shallow copy by overriding the clone() method but the array list always remains shared by any copy of the object. Before diving into deep copies and the like I think I need advice on whether that's the best route.
Here's an example of the object I need to find a way to duplicate.
public class QueryParameters implements Cloneable {
protected HashMap<String,String> foundArgs = new HashMap<String,String>();
protected ArrayList<ActionType> action_types = new ArrayList<ActionType>();
protected String lookup_type = "lookup";
protected Location loc;
protected Vector player_location;
protected int id = 0;
protected int radius;
protected boolean allow_no_radius = false;
protected String player;
protected String world;
protected String time;
protected String entity;
protected String block;
// ... lots of getters/setters
}
I could always make a new instance and use getters/setters to transfer the data but that feels too verbose to me - there are about 15 fields I'd have to copy over and if I ever add new ones I'd need to remember to add them here.
What's the best way for me to obtain a new instance/clone so that changes to action_types doesn't affect the original object
You don't need to use getters and setters if you "clone your own class". A constructor like this maybe?
private QueryParameter(QueryParameter other)
{
foundArgs = new HashMap<String, String>(other.foundArgs);
action_types = new ArrayList<ActionType>(other.action_types);
// etc
}
// As a static method, or
public static QueryParameter copyOf(QueryParameter other)
{
return new QueryParameter(other);
}
// as an instance method
public QueryParameter copy()
{
return new QueryParameter(this);
}
This is one solution among many...
I suggest writing a clone method that uses super.clone() to copy most of the fields, and then replaces the ArrayList in the clone. Something like this:
import java.util.ArrayList;
public class QueryParameters implements Cloneable {
#Override
public String toString() {
return "QueryParameters [action_types=" + action_types + ", otherData="
+ otherData + "]";
}
protected ArrayList<String> action_types = new ArrayList<String>();
protected String otherData;
#Override
public QueryParameters clone() throws CloneNotSupportedException {
QueryParameters cloned = (QueryParameters) super.clone();
cloned.action_types = new ArrayList<String>(action_types);
return cloned;
}
public static void main(String[] args) throws CloneNotSupportedException {
QueryParameters test = new QueryParameters();
test.otherData = "a field";
test.action_types.add("xyzzy");
test.action_types.add("abcde");
System.out.println("Original: " + test);
QueryParameters clone = test.clone();
clone.action_types.add("A new action type");
System.out.println("Modified clone: " + clone);
System.out.println("Original after clone modification: " + test);
}
}

Categories