Related
I created an object N, which has some attributes, like this:
public class LogEvidence {
private String comment;
private String url;
private String time;
public LogEvidence(String comentario, String url, String tiempo) {
super();
this.comment = comentario;
this.url = url;
this.time = tiempo;
}
public String getComentario() {
return comment;
}
public void setComentario(String comentario) {
this.comment = comentario;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getTiempo() {
return time;
}
public void setTiempo(String tiempo) {
this.time = tiempo;
}
#Override
public String toString() {
return "LogEvidence [comentario=" + comment + ", url=" + url + ", tiempo=" + time + "]";
}
}
Now I want to do something like this:
ArrayList<LogEvidence>log = new ArrayList<LogEvidence>();
I want go through the list and add all the attributes to my object, I mean something like this:
log.setComment("comment one");
log.setUrl("http://google.com");
log.setTime("04:20");
Maybe this is not possible and I have to do something like the following?
List list= new List();
LogEvidence object1= new LogEvidence ();
object1.setComment("comment");
object1.setUrl("http://url.com");
object1.setTime(20);
lista.add(object1);
This is how you can do it:
Create an object of LogEvidence.
LogEvidence logEvidence = new LogEvidence();
logEvidence.setComentario("comment one");
logEvidence.setUrl("http://google.com");
logEvidence.setTiempo("04:20");
and add it into the array list.
log.add(logEvidence);
So, you can then create more objects and keep putting in the list. Since your list is named as log, so that is why you will add in log
Explaining it a little more, it should be something like this:
List<LogEvidence> logEvidenceList = new ArrayList<>();
LogEvidence logEvidence1 = new LogEvidence();
logEvidence1.setComentario("comment one");
logEvidence1.setUrl("http://google.com");
logEvidence1.setTiempo("04:20");
logEvidenceList.add(logEvidence1);
LogEvidence logEvidence2 = new LogEvidence();
logEvidence2.setComentario("comment one");
logEvidence2.setUrl("http://google.com");
logEvidence2.setTiempo("04:20");
logEvidenceList.add(logEvidence2);
....
....
....
Or through constructor call, this will become more concise and readable.
List<LogEvidence> logEvidenceList = new ArrayList<>();
LogEvidence logEvidence1 = new LogEvidence("comment one","http://google.com","04:20");
logEvidenceList.add(logEvidence1);
LogEvidence logEvidence2 = new LogEvidence("comment one","http://google.com","04:20");
logEvidenceList.add(logEvidence2);
....
....
....
Now, when you want to retrieve objects from the list, you can traverse the list and get one by one like;
for (LogEvidence evidence : logEvidenceList) {
System.out.println(evidence);
}
For more information about ArrayList
As Kon commented, you are trying to act upon an object that will be within the list, rather than the list itself.
There are a few ways to do this, but since you have a parameterized construtor, the easiest would be this:
ArrayList<LogEvidence> log = new ArrayList<LogEvidence>();
log.add(new LogEvidence("comment one", "http://url.com", "04:20");
What's being done:
We create the list with new ArrayList<LogEvidence>() and assign it to a variable called log.
Then, we create a new LogEvidence object, already assigning it's data through it's constructor's parameters, with new LogEvidence("comment one","http://url.com","04:20").
Since it will be stored in the list, we can use it anonymously. We add it to the list directly, using the list's .add(E e) method, rather than assigning it to a variable.
You don't need to define or assign unnecessary variables, in this case.
And if you need to access any specific LogEvidence from the list, you can use the .get(int index) method. In this case, log.get(0), to return the first element, would return the object you just inserted in the example code above.
You can also use a FOR-EACH LOOP to act upon all objects in the list, in iterating manner. Here is an example that prints the list:
for (LogEvidence evidence : log) {
System.out.println(evidence);
}
Consider I am given an array of Classes and string representation of an Object. How can I get which Class this Object belongs to?
I thought of this approach but I don't know how to achieve it:
Iterating over Class array and then getting all instances of that
class.Then convert each instance to its String representation and then
check if it equals given String.
The problem I'm having is how do I get all Instances of that Class?
We can use getInstance() if all are Singleton class but what if not?
Please clarify my if I have any misunderstanding.
import java.util.*;
public class Class_instance {
public static void main(String args[]){
List<Class> class_list = new ArrayList<Class>();
Test_class x = new Test_class();
Test y = new Test();
class_list.add(x.getClass());
class_list.add(y.getClass());
String ex = x.toString();
}
}
How to know what class ex represents here?
Short answer - no, this won't work.
The toString() method returns a textual representation of the object, but there is no guarantee this will include the class name. For example, for Strings, toString() returns the value of the string. In particular any textual representation could come from a string.
If you have a specific list of classes you want to look for (and they have identifiable values), you could write regexes which would identify their toString values.
Using the Class object directly is more likely to be what you're after here:
public static void main(String [] args){
Class[] possibleClasses= {String.class, Integer.class};
System.out.println(identifyClass("string", possibleClasses));
System.out.println(identifyClass(4, possibleClasses));
}
#SuppressWarnings("raw")
public static Class identifyClass(Object o, Class[] possibleClasses){
// Ignore null inputs
if (o==null){
return null;
}
// Find the first entry which matches o
for (Class c : possibleClasses){
if (c.isInstance(o)){
return c;
}
}
// If no matches are found, return null.
return null;
}
Although that said, maybe this would be enough?
System.out.println(ex.getClass().getName());
As mentioned we need to know what string representation means.
In most application (AFAIK) instanceof should suffice to check if object belong to a certain class or not . Another way is to define a overwrite the toString method
public class House {
public String address;
public String type;
public House(String add){
this.address = add;
}
#Override
public String toString() {
return (address + "-" + type) ;
}
}
If given a String sample = "Hogwart-Castle"; You can use the following :
houseObj.toString().equals(sample);
If you own the classes you want to search, you can keep the track of their instances by creating a new class (I called it MyObject) with a static field that you fill when a new object of that class is created, and then extending the classes you want to keep track with this new class.
public class MyObject {
private static Map<Class<?>, List<WeakReference<?>>> instances = new HashMap<>();
public MyObject() {
if (!instances.containsKey(getClass())) {
instances.put(getClass(), new ArrayList<>());
}
instances.get(getClass()).add(new WeakReference<>(this));
}
public static List<Object> getInstances(List<Class<?>> classes) {
List<Object> result = new ArrayList<>();
for (Class<?> clazz : classes) {
if (instances.containsKey(clazz)) {
Iterator<WeakReference<?>> iterator = instances.get(clazz).iterator();
while (iterator.hasNext()) {
WeakReference<?> ref = iterator.next();
if (ref.get() == null) {
iterator.remove();
} else {
result.add(ref.get());
}
}
}
}
return result;
}
}
Then you can use it like this:
public class Main {
public static void main(String[] args) {
Dog d1 = new Dog("I'm a dog");
Dog d2 = new Dog("I'm an animal");
Cat c1 = new Cat("I'm an animal");
List<Class<?>> classList = new ArrayList<>();
classList.add(Dog.class);
find("I'm an animal", classList); // Found a Dog
classList.add(Cat.class);
find("I'm an animal", classList); // Found a Dog and a Cat
find("I'm a dog", classList); // Found a Dog
}
private static void find(String str, List<Class<?>> classes) {
for (Object o : MyObject.getInstances(classes)) {
if (o.toString().equals(str)) {
System.out.println("Found a " + o.getClass().getSimpleName());
}
}
}
}
My Dog class (and similarly the Cat class) looks like this:
public class Dog extends MyObject {
String description;
public Dog(String description) {
this.description = description;
}
#Override
public String toString() {
return description;
}
}
Beware that toString() doesn't return a unique representation of an object (as shown in my example), unless you have full control over the toString() of that objects and you ensure it yourself.
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")
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")
I put some value to ArrayList<"Object">
ArrayList<Object> mData = new ArrayList<Object>();
AdListData data = new AdListData();
data.Id = json_data.getInt("ad_uid");
data.User_id = json_data.getInt("user_id");
mData.add(data);
And after I need to convert ArrayList<"Object"> to ArrayList<"AdListData">
How can I do this? Example:
ArrayList<AdListData> array = new ArrayList<AdListData>();
array = mData;
Why I need to do this? I use AsyncTask and on onPostExecute a get data like this
protected void onPostExecute(ArrayList<Object> result) {
// Pass the result data back to the main activity
mDownloadCompleteListener.getDownloadCompleteState(result);
}
this example show that a get only on type of arraylist
ArrayList<Object>
OR
ArrayList<AdListData>
But in my case I want to use it for different Objects like this
ArrayList<Object> mData = new ArrayList<Object>();
if(mType == "get_ad_data")
{
AdListData data = new AdListData();
data.Id = json_data.getInt("ad_uid");
data.User_id = json_data.getInt("user_id");
mData.add(data);
}
else
{
AnotherClass data = new AnotherClass();
data.Id = json_data.getInt("ad_uid");
data.User_id = json_data.getInt("user_id");
mData.add(data);
}
return mData;
`
And when listener call I want to convert it in needed Array of objects
#Override
public void getDownloadCompleteState(ArrayList<Object> ad_list) {
// TODO Auto-generated method stub
ArrayList<AdListData> array = new ArrayList<AdListData>();
array = ad_list;
}
Check out java generics. When you pass in your array list, define it as ArrayList<T extends Object> or ArrayList<? extends Object>. Then when you're passing or getting values you can define T as the class of your choice or check if the object is an instance of the class you want. There's a ton of information and examples on java generics so you can find what fits your needs w/o me posting a bunch of examples.
I don't think it's possible to just automatically assign ArrayList<Object> to ArrayList<AdListData> since there is no guarantee that all of the data is of type AdListData.
Why you are making life too complicated..
Ever heard about Moduler Code, Interfaces, Abstract classes???
I ll suggest you to write one Interface or Abstract class over your AdListData and AnotherClass.. (I am assuming they share IS A relationship..) If not.. write two diff AsyncTasks for those.. and if they share common code you can use functions like utility functions..
doing this your code will be much more readable and simple..
now, to ans your question I ll just write some snippet..
public class Test {
int data;
public static <T extends Object> void foo(ArrayList<T> l) {
T firstObj = l.get(0);
if (firstObj != null) {
if (firstObj instanceof Test) {
System.out.println("yay.. I am list of test obj " + l);
} else {
System.out.println("m just another list.. :( " + l);
}
}
#Override
public String toString() {
return data + "";
}
public static void main(String[] args) {
ArrayList<Test> l = new ArrayList<Test>();
Test t1 = new Test();
t1.data = 1;
Test t2 = new Test();
t2.data = 2;
Test t3 = new Test();
t3.data = 3;
Test t4 = new Test();
t4.data = 4;
l.add(t1);
l.add(t2);
l.add(t3);
l.add(t4);
foo(l);
ArrayList<Integer> l2 = new ArrayList<Integer>();
l2.add(1);
l2.add(2);
l2.add(3);
l2.add(4);
foo(l2);
}
}