Hi I have a enum array and it is a field of my class. And I am implementing clone method of this class. But I have some ideas about copying array of enums but what is the formal way of copying an enum array ?
public enum StateEnum {
START, PLAY, PAUSE , STOP
}
class MyClass{
StateEnum[] stateEnums;
public Object clone(){
MyClass copyClass = new MyClass();
// copy enums
}
}
Enum values are (or should be) immutable, so you don't need to copy them.
You can just make a shallow copy of the array by calling System.arraycopy().
As said by SLaks, use the System.arraycopy to clone your array. Further, the
MyClass copyClass = new MyClass();
should be replaced by
MyClass copyClass = (MyClass)super.clone();
The reason for this is explained in this article in full detail, where the end of page 2 discusses the common pitfalls while implementing a clone method
Related
I'm currently sitting at an exercise, which wants me to create a Java program based on an already finished documentation HTML sheet.
For example, one entry states
reversedArray
public static Object[] reversedArray(Object[] array)
Based on the name, we can assume the method should return an array in the reversed order of array.
Now my question isn't about how to create the said array, but more about the Object[] terminology. What does it mean? Should I create a bunch of methods through overloading each with a specific array type (e.g. String[], int[], ...) or literally an Object[]?
It's the latter, how does an object array work? Based on the name, I assume it's an array that can hold objects, but I'm unsure what this means in practice.
Object[] is basically just an array of objects (best explanation award right here please ----> ☐ )
Jokes aside, in Java, any object is derived from the class Object so basically, this array can store any object of any class. It's mostly useful when you just want to carry an instance (or several instances) of different classes, but the type of said instance is not important.
Let's say you have multiple classes that are not necessarily related :
Class Dog {
String name;
public Dog(String name) {
this.name = name
}
public String toString() {
return "Hello! I am a dog called " + this.name;
}
}
Class Refrigerator {
public Refrigerator() {
}
public String toString() {
return "I am a refrigerator";
}
}
Since both classes are implicitly derived from Object and that Object implements the method toString() you can override that method in both of you class declarations.
Then you can store any instance of these in a Object and call the method toString(), like so :
Dog myDog = new Dog("Spike");
Object anyObject = myDog;
System.out.println(anyObject.toString()); //would print the result of your "toString()" method in the Dog class :
//"Hello! I am a dog called Spike"
Refrigerator myFridge = new Refrigerator();
Object secondObject = myFridge;
System.out.println(secondObject.toString()); //would print the result of your "toString()" method in the Refrigerator class :
//"I am a refrigerator"
This allows you to create a method that accepts any object and treats them the same and assign any object in argument :
public void printWhatYouAre(Object o) {
System.out.println(o.toString());
}
public void doingSomething() {
Dog myDog = new Dog("Spike");
Refrigerator myFridge = new Refrigerator();
printWhatYouAre(myDog);
printWhatYouAre(myFridge); //would print the same as above
}
In your case, your method only needs to rearrange an array, which means it doesn't even need the method toString nor does it need to know what the objects are. It just needs to store an array of something into an other array of something in a different order.
Here is a nice reading about polymorphism in Java, which is basically applicable in any language, but the examples that are used are wrote in Java. The whole site actually is a pretty good reference, so it's worth taking a look, especially the OOP sections which are the most related to your post. ;)
As the name already states, the method should create a new array in
the reversed order of "array".
The method name only says to "reverse" the array; whether it's just a matter of modifying the actually supplied array or constructing a new one is something you'll need to clarify with the author of the requirement if it's not clear.
Now my question isn't about how to create said array, but more about
the "Object[]" terminology. Basically, I'm unsure what to do. Does
said "Object[]" mean, I should create a bunch of methods through
overloading each with a specific array type (e.g. String[], int[],...)
or literally an Object[] array?
No, you only have to create overloads for the primitive types i.e. int[], long[] etc and that's only if your requirement says so. the aforementioned method should be able to consume Object[], String[] , Integer[] , Double[] etc...
It it's the latter, how does an object array work? Based on the name I
assume, it's an array that can hold objects, but I'm unsure what this
means in practice.
The method name has nothing to do with what an array can hold, the method argument is an array of Object's and it's as simple as that.
Reading you might find useful:
Arrays
I want to ask you how can i copy firstClass objects to secondClass objects?
Is this possible to figure it out by using clone()?
The situation looks like this:
I have a class f.x. firstClass. And I need to clone firstClass objects to secondClass objects (and these cloned objects must be stored into array)
Thanks
EDITED:
sorry for a little information. But my task looks like this:
Write a Garage class whose objects can hold up to some number of Vehicle objects in an
array. Make Garage a Cloneable type, and write a proper clone method for it. Write a Garage.main
method to test it.
It's not cloning. If you have two unrelated classes, the best you can do is write a constructor for SecondClass that takes FirstClass object as an argument and writes all the values into the proper fields:
public SecondClass (FirstClass source){
this.valueA = source.getValueA();
this.valueB = source.getBValue();
this.valueC = source.getProperCValue();
...
}
By convention, Object.clone() method and its overrides should always return an object of the original type.
x.clone().getClass() == x.getClass()
So it should be impossible to create an object of different type if clone() is properly implemented and used.
something like this?!
class Foo{
private String bar;
public Object clone(){
Foo f=new Foo();
f.setBar(this.bar);
//filling and copy the f attributes
guys.add(f);
}
///
private final static List<Foo> guys=new ArrayList<>();
///
}
I think that a final reference to an array of enums should be immutable.
The uniqueness and singularity of enums is enforced by the JVM, so I believe it is safe to say that they are immutable.
A final reference cannot be changed, so the reference is immutable.
But ... what about the array? Might it still be possible to subvert the array that contains the enum references?
I have a list of enums that correspond to database columns. These column names and their associated data do not change, so ... I would like to have the list as a class variable like so:
static final List<MetaData<Client>> C_COLUMNS =
DataTables.CLIENTS.getTableColumnsAsEnums();
where CLIENTS is the DataTable enum for which a list of column enums is being generated. The method that does this follows:
public <T extends DB> List<MetaData<T>> getTableColumnsAsEnums() {
Class<? extends MetaData> cls = this.columnsEnumToken();
return new ArrayList(Arrays.<MetaData<T>>asList(cls.getEnumConstants())); }
Am I right? This ought to become part of a multi-threaded design, and so I am concerned about the way that making this critical list of static data would render by app very vulnerable ... if it actually were mutable.
But ... what about the array? Might it still be possible to subvert the array that contains the enum references?
Yes. All arrays in Java are mutable, irrespective of how you declare the variable that holds the reference to the array.
If you want to avoid this "risk", then you must not expose the array; i.e. you need to declare it as private. You could then do one (or more) of the following:
Define a static method that will create and return a copy of the array. (Probably not the best option here ...)
Define a static get(int) method that returns the ith element of the array.
Wrap the array in a list (using Arrays.asList) and create an unmodifiable wrapper for it (using Collections.unmodifiableList).
If you want to get the public <T extends DB> List<MetaData<T>> getTableColumnsAsEnums() to return an immutable List you need to use Collections.unmodifiableList()
Also when you are using an unmodifiable list you don't have to worry about the internal array because the toArray method will return an copy of the internal array, not a reference to the internal array itself. This is true for all the Collections.
The REFERENCE is immutable, the content of that reference is not, that's just how things work.
So the following won't work
public enum TheEnum {
//......
}
final TheEnum[] arr = new TheEnum[5];
var = new TheEnum[6];
but this will work
public enum TheEnum {
OPTION_ONE;
//......
}
final TheEnum[] arr = new TheEnum[5];
var[1] = TheEnum.OPTION_ONE;
This question already has answers here:
How do I copy an object in Java?
(23 answers)
Closed 9 years ago.
I am having difficulties understanding the concept of "deep copy" in Java.
Assuming I had a class "myClass" with various parameters in it. I tried writing a method "copy" which was supposed to return a deep copy of such class as:
public myClass copy() {
myClass deepCopy = new myClass();
deepCopy.varA = varA;
deepCopy.varB = varB;
return deepCopy;
}
Can somebody confirm whether this is indeed "deep copying" or if I am doing something wrong?
Thanks!
If you don’t want to implement deep copy yourselves then you can go for serialization. It does implements deep copy implicitly and gracefully handling cyclic dependencies.
A nice article about Deep Copy, Clone and Shallow Copy can be found here.
Only If:
Class "myClass" only contains varA and varB.
Class "myClass" has no superclass.
Variables varA and varB are of an elementary type (ie. String, int, long, ....). Otherwise you'll have to apply the same copying process to them too.
In deep copy When the copied object contains some other object its references are copied recursively
see more at here
A deep copy occurs when an object is copied along with the objects to which it refers.
If suppose there is a MainObject1 of MainObject type having fields "field1" of int type, and "ContainObject1" of ContainObject type. When you do a deep copy of MainObject1, MainObject2 is created with "field3" containing the copied value of "field1" and "ContainObject2" containing the copied value of ContainObject1. So any changes made to ContainObject1 in MainObject1 will not be reflected in MainObject2.
In your implementation, if you are trying to simulate deep copy, then you should have only these two variables : varA and varB in your class of primitive type.
This would only be a deep copy if varA and VarB were primitive types. If they are reference types than your new object will point at the same instances of these classes as the original.
An easy way to implement deep copy is via serialization. Apache commons lang provides a utility method for this (SerializationUtils.clone( foo ) ).
It does however requires that all the objects are serializable.
If this is not the case for you XStream can be used for deep cloning with minimal development effort.
http://x-stream.github.io/
Observe output of following program.
1> See output without clone() method. Remove clone() method from following program. (example of shallow copy)
2> See output with clone() method. (Example Deep copy. See ArrayList object's output)
import java.util.ArrayList;
import java.util.List;
public class DeepCopy implements Cloneable {
private List<String> hobbiesList;
private int age;
private String name;
private float salary;
public static void main(String[] args) throws CloneNotSupportedException {
DeepCopy original = new DeepCopy();
original.name="AAA";
original.age=20;
original.salary=10000;
original.hobbiesList = new ArrayList<String>();
original.hobbiesList.add("Cricket");
original.hobbiesList.add("Movies");
original.hobbiesList.add("Guitar");
original.hobbiesList.add("Eating");
DeepCopy cloned = (DeepCopy) original.clone();
System.out.println("original:="+original);
System.out.println("cloned :="+cloned);
System.out.println("After adding two more hobbies in 'original' which untimately reflected in 'cloned'");
cloned.name="BBB";
cloned.age=27;
cloned.salary=18237;
cloned.hobbiesList.add("Trecking");
System.out.println("original :="+original);
System.out.println("cloned changed:="+cloned);
}
#Override
protected Object clone() throws CloneNotSupportedException {
DeepCopy clone = (DeepCopy)super.clone();
clone.hobbiesList = new ArrayList<String>(clone.hobbiesList);
return clone;
}
#Override
public String toString() {
return "My name is (String)"+name + " having age (int)"+age+". I earned (float)"+salary+" and hobbies are (ArrayList)"+hobbiesList;
}
}
I'm trying to clone an instance of a custom class I made called CSP. I have one instance called csp and I want to make a clone of csp called cspclone. Here is what I'm using to do that:
CSP cspclone = new CSP((csp.x).clone(), (csp.d).clone(), (csp.c).clone());
For some reason though when I pass cspclone to a method that modifies it csp gets modified also as if I forgot the .clone() functions but I didn't! Why is this happening?!
Override the clone method in CSP:
public class CSP {
private String aField;
private int[] array;
private int[][] twoDArr;
private List<ALContent> list; //here ALContent also needs to override clone properly
#Override
public Object clone() {
CSP clone = new CSP();
clone.aField = this.aField;
clone.array = new int[this.array.length];
System.arraycopy(this.array, 0, clone.array, 0, this.array.length);
clone.list = new ArrayList<ALContent>();
for(ALContent content : this.list) {
clone.list.add(content.clone()); //make sure you add the clone of the content
}
clone.twoDArr = new int[this.twoDArr.length][];
for(int i=0; i<this.twoDArr.length; i++) {
clone.twoDArr[i] = new int[this.twoDArr[i].length];
System.arraycopy(this.twoDArr[i], 0, clone.twoDArr[i], 0, this.twoDArr[i].length);
}
return clone;
}
}
Then you can do:
CSP csp = new CSP();
CSP cspClone = (CSP) csp.clone();
If your properties of array type use System.arraycopy
According to http://download.oracle.com/javase/1.3/docs/api/java/lang/Object.html#clone%28%29
this method creates a new instance of the class of this object and initializes all its fields with exactly the contents of the corresponding fields of this object, as if by assignment; the contents of the fields are not themselves cloned. Thus, this method performs a "shallow copy" of this object, not a "deep copy" operation.
You might have to override the clone method and clone() a reference type attribute within the object (i.e., perform deep copy operation).
To solve your problem you need deep cloning. The default clone method does a shallow copy. See Object.clone().
Here are some approaches. All have advantages and drawbacks.
Override: Override the clone() method.
Serialization: Write the object to a stream and a read it back from the stream.
Reflection: Here is a tutorial on reflection.
Use a deep close library, such as Java Deep-Cloning library.
Here are several other stackoverflow discussions of cloning.
Java: recommended solution for deep cloning/copying an instance
Deep clone utility recomendation
How to clone ArrayList and also clone its contents?