Suppose I have collection, stored in
Collection<V> member;
or in
C member;
How to clone this class with also cloning this member?
How to clone this class with also cloning this member?
I assume you're overriding the clone method. So you could use the provided runtimeType of member to get a new instance:
public class MyObject<V, C extends Collection<V>> {
private C member = ...;
#Override
public MyObject clone(){
MyObject clone = new MyObject();
if(member != null){
try {
clone.member = member.getClass().newInstance();
clone.member.addAll(member);
} catch(InstantiationException | IllegalAccessException ignore){}
}
// clone other properties
return clone;
}
}
But this is quite dirty because you can never ensure that C has a default constructor or as mentioned by #shmosel, the collection could even be imutable. E.g. the addAll() call fails.
To overcome the above dirty way you could require a Supplier<C> when creating an instance of MyObject that way you could create your own collections as you wish:
private final Supplier<C> factory;
public MyObject(Supplier<C> factory){
this.factory;
}
And only create the member when it is first time used. By invoking factory.get().
That way you safely create the member variable when cloning the object. But then there's still the case with the imutability which is probably the breaker of any approach to copy the values from the member to clone.member.
What considered to be the best & common practice if I want to make sure that after setter is called the object cannot be modified from outside? In the code there is detailed simple self explained example, With 2 options dilemma.
//caller scope
CustomObject original = new CustomObject(params...); //original state 1
MyClass mMyClass = new MyClass(original);
original.modifyMe(params...); //original state 2
mMyClass.setCustomObject(original);
original.modifyMe(params...); //original state 3
/*!!!REQUIREMENT: mMyClass.CustomObject should be in state 2!!!*/
class MyClass {
private CustomObject mObject;
public MyClass() {
this.mObject = new CustomObject();
}
public MyClass(CustomObject obj) {
this.mObject = obj.Clone();
}
//mObject is private, modified only through setter
public getCustomObject() {
return this.mObject;
}
public setCustomObject(CustomObject obj) {
//Option 1 in the caller
//mMyClass.setCustomObject(new CustomObject(params...));
this.mObject = obj;
//Option 2 in the caller
//mMyClass.setCustomObject(callerCustomObject);
this.mObject = obj.Clone();
}
}
I wouldn't use clone here. Rather than making inefficient defensive copies, try making CustomObject immutable. You can modify state by adding withXXX methods (roughly equivalent to setXXXX) but they create a new instance of the host object (rather than the Object being passed in). Project lombok comes with some handy preprocessor annotations for creating Immutable objects with Withers. Also see the Immutables 2.0 project.
#AllArgsConstructor
class CustomObject {
#Wither #Getter
private final int state;
}
CustomObject one = new CustomObject(1);
CustomObject two = one.withState(2);
assertThat(one.getState(),equalTo(1));
assertThat(two.getState(),equalTo(2));
By using genuine Immutable Objects you will incur much less memory (& GC) and CPU overhead than with defensive copies - as well as much simpler code.
I have two (sibling) classes, both is subclass of the same parent. Parent contains all the methods that is shared by the two sibling, and the sibling classes contain only methods that are not shared and has different implementations.
Example,
class Parent() {
}
class Sibling1 extends Parent() {
byte[] sharedSecret;
int sharedSecretLength;
public generateKey() {
sharedSecret = keyAgree.generateSecret());
sharedSecretLength = sharedSecret.length);
}
}
class Sibling2 extends Parent() {
byte[] sharedSecret2;
int sharedSecretLength2;
public generateKey() {
sharedSecret2 = new byte[sharedSecretLength];
sharedSecretLength2 = keyAgree.generateSecret(sharedSecret2, 0);
}
public int getSharedSecretLength() {
return sharedSecretLength();
}
}
As you can see, both contains same method but implemented differently. My question is, if objects of both class (sibling1 and sibling2) are created AND obj2 generateKey to be generated successfully depends on sharedSecretLength of obj1. Example,
Parent obj1 = new Sibling1();
Parent obj2 = new Sibling2();
obj1 is instantiated in different class (Server class that I created) and obj2 in different class (Client that I created). If obj1 invoke it's own generateKey --> ((Sibling1)obj1).generateKey(), how can I use use getSharedSecretLength on the same object (obj1) to relay the needed information over to obj2's generateKey to generate successfully? I tried something like (in obj2's generateKey() ):
sharedSecret2 = new byte[Sibling1.sharedSecretLength];
...and it didn't work. Creating Sibling1 obj1 inside of Sibling2 class and then call it that way, for example,
Sibling1 xx = null;
.
.
sharedSecret2 = new byte[((Sibling1)xx).sharedSecretLength];
doesn't work because xx is new object. I am trying to use the old obj in which it generated it's key and contains sharedSecretLength that is not 0
If both obj1 and obj2 were created in the same class, it would have been easier.
Please help point me to the right direction
Instead of
((Sibling1)xx).sharedSecretLength
call it like
((Sibling1)xx).getSharedSecretLength()
In java, you have pass the empty parenthesis if it doesn't accept parameter and it doesnt work by field name, you will have to give the same method name as to what you have defined.
It sounds like you should refactor like this so that the generateKey method on Sibling2 has the argument it requires:
Sibling1 obj1 = new Sibling1();
obj1.generateKey();
Siblibg2 obj2 = new Sibling2();
obj2.generateKey(obj1.getSharedSecretLength());
This question already has answers here:
Java: recommended solution for deep cloning/copying an instance
(10 answers)
Closed yesterday.
I want to create a list/array of object with the same parent class which then I will use it for reference. but i dont know how to clone those object to make a new object.
here is the example
BigFoo a;
SmallFoo b;
ChickenFoo c;
List<Foo> foos;
foos.add(a);
foos.add(b);
foos.add(c);
Foo foo = foos.get(1).clone();
but in Java i found no clone function in the default function. I wonder how this is accomplished?
The general suggestion: use a copy constructor. In fact, only a class itself knows how to create a clone of itself. No class can clone an instance of another class. The idea goes like this:
public class Foo {
public List<Bar> bars = new ArrayList<Bar>();
private String secret;
// Copy constructor
public Foo(Foo that) {
// new List
this.bars = new ArrayList<Bar>();
// add a clone of each bar (as an example, if you need "deep cloning")
for (Bar bar:that.bars) {
this.bars.add(new Bar(bar));
}
// clone the secret value
this.secret = new String(that.secret);
}
// ...
}
So if we want to clone a foo, we simply create a new one based on foo:
Foo clonedFoo = new Foo(foo);
That's the recommended way to clone an instance.
copy constructor works well with inheritance. Consider a subclass
public ChildFoo extends Foo {
private int key;
public ChildFoo(ChildFoo that) {
super(that);
this.key = that.key;
}
}
Foo has a copy constructor and ChildFoo simply calls it from it's own copy constructor.
Your example is possible but not advisable. What will happen:
Foo a = new Foo();
ChildFoo b = new ChildFoo(a);
This would require a constructor on ChildFoo like:
public ChildFoo(Foo that) {
// call the copy constructor of Foo -> no problem
super(that);
// but how to initialize this.key? A Foo instance has no key value!
// Maybe use a default value?
this.key = 0;
}
Technically not a challenge but b is not a clone of a because the objects don't have the same type. So this (your example) is not cloning.
One easy way would be to use a json mapper (Jackson or Gson) and write out the object as a string and then creating the clone object by using the string.
Newbie Java question. Say I have:
public class Car{
...
}
public class Truck extends Car{
...
}
Suppose I already have a Car object, how do I create a new Truck object from this Car object, so that all the values of the Car object is copied into my new Truck object?
Ideally I could do something like this:
Car c = new Car();
/* ... c gets populated */
Truck t = new Truck(c);
/* would like t to have all of c's values */
Would I have to write my own copy constructor? This would have to be updated everytime Car gets a new field...
Yes, just add a constructor to Truck. You will probably want to add a constructor to Car also, though not necessarily public:
public class Car {
protected Car(Car orig) {
...
}
public class Truck extends Car {
public Truck(Car orig) {
super(orig);
}
...
}
As a rule it's generally best to make classes either leaf (and you might want to mark those final) or abstract.
It looks as if you want a Car object, and then have the same instance turn into a Truck. A better way of doing this is to delegate behaviour to another object within Car (Vehicle). So:
public final class Vehicle {
private VehicleBehaviour behaviour = VehicleBehaviour.CAR;
public void becomeTruck() {
this.behaviour = VehicleBehaviour.TRUCK;
}
...
}
If you implement Cloneable then you can "automatically" copy an object to a instance of the same class. However there are a number of problems with that, including having to copy each field of mutable objects which is error-prone and prohibits the use of final.
If you are using Spring in your project you may use ReflectionUtils.
Yes, you have to do this manually. You'll also need to decide how "deeply" to copy things. For instance, suppose the Car has a collection of tyres - you could do a shallow copy of the collection (such that if the original object changes the contents of its collection, the new object would see the change too) or you could do a deep copy which created a new collection.
(This is where immutable types like String often come in handy - there's no need to clone them; you can just copy the reference and know that the contents of the object won't change.)
Would I have to write my own copy constructor? This would have to be
updated everytime Car gets a new field...
Not at all!
Try this way:
public class Car{
...
}
public class Truck extends Car{
...
public Truck(Car car){
copyFields(car, this);
}
}
public static void copyFields(Object source, Object target) {
Field[] fieldsSource = source.getClass().getFields();
Field[] fieldsTarget = target.getClass().getFields();
for (Field fieldTarget : fieldsTarget)
{
for (Field fieldSource : fieldsSource)
{
if (fieldTarget.getName().equals(fieldSource.getName()))
{
try
{
fieldTarget.set(target, fieldSource.get(source));
}
catch (SecurityException e)
{
}
catch (IllegalArgumentException e)
{
}
catch (IllegalAccessException e)
{
}
break;
}
}
}
}
you can use reflection i do it and work fine for me:
public Child(Parent parent){
for (Method getMethod : parent.getClass().getMethods()) {
if (getMethod.getName().startsWith("get")) {
try {
Method setMethod = this.getClass().getMethod(getMethod.getName().replace("get", "set"), getMethod.getReturnType());
setMethod.invoke(this, getMethod.invoke(parent, (Object[]) null));
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
//not found set
}
}
}
}
Would I have to write my own copy constructor? This would have to be updated everytime Car gets a new field...
Essentially, yes - you can't just convert an object in Java.
Fortunately you don't have to write all the code yourself - look into commons-beanutils, specifically methods like cloneBean. This has the added advantage that you don't have to update it every time it gets a new field!
You could always use a mapping Framework such as Dozer. By default (without further configuration), it maps all fields of the same name from one object to another using the getter and setter methods.
Dependency:
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>5.5.1</version>
</dependency>
Code:
import org.dozer.DozerBeanMapper;
import org.dozer.Mapper;
// ...
Car c = new Car();
/* ... c gets populated */
Truck t = new Truck();
Mapper mapper = new DozerBeanMapper();
mapper.map(c, t);
/* would like t to have all of c's values */
You will need a copy constructor, but your copy constructor can use reflection to find the common fields between the two objects, get their values from the "prototype" object, and set them on the child object.
You could use the reflection API to loop through each of the Car fields and assign the value to the equivalent Truck fields. This can be done within truck. Further it is the only way to access the private fields of Car - at least in an automatic sense, providing that a security manager is not in place and restricting access to private field.
The solutions presented above have limitations you should be aware of. Here's a short summary of algorithms for copying fields from one class to another.
Tom Hawtin: Use this if your superclass has a copy constructor. If it does not you will need a different solution.
Christian: Use this if the superclass does not extend any other class. This method does not copy fields recursively upwards.
Sean Patrick Floyd: This is a generic solution for copying all fields recursively upwards. Be sure to read #jett's comment that a single line must be added to prevent an endless loop.
I reproduce Sean Patrick Floyd's analyze function with the missing statement:
private static Map<String, Field> analyze(Object object) {
if (object == null) throw new NullPointerException();
Map<String, Field> map = new TreeMap<String, Field>();
Class<?> current = object.getClass();
while (current != Object.class) {
Field[] declaredFields = current.getDeclaredFields();
for (Field field : declaredFields) {
if (!Modifier.isStatic(field.getModifiers())) {
if (!map.containsKey(field.getName())) {
map.put(field.getName(), field);
}
}
}
current = current.getSuperclass(); /* The missing statement */
}
return map;
}
I know this is an OLD question, but I hate to leave out dated answers when things have improved.
Using JSON is much easier. Convert it to JSON and back again as child.
Here is an Android Kotlin Example.
val gson = Gson()
val childClass = gson.fromJson(
gson.toJson(parentObject),
object: TypeToken<ChildObject>(){}.type
) as ChildObject
I think in Java it would be basically.
Gson gson = new Gson()
ChildObject child = (ChildObject) gson.fromJson(
gson.toJson(parentObject),
TypeToken<ChildObject>(){}.getType()
)
And you're done, no messiness, just simple json in, json out.
If you don't have gson, I'm sure you have other json options available to you.
It's a WHOLE lot cleaner and faster than doing reflection and all that craziness.