I have an object that I need to copy in Java. I need to create a copy and run some tests on it without changing the original object itself.
I assumed that I needed to use the clone() method, but this is protected. Having done some research on the net, I can see that this can be overriden with a public method in my class. But I cannot find an explanation on how to do this. How could this be done?
Also, is this the best way of achieving what I need?
Another option by using Copy Constructor (from Java Practices):
public final class Galaxy {
public Galaxy (double aMass, String aName) {
fMass = aMass;
fName = aName;
}
/**
* Copy constructor.
*/
public Galaxy(Galaxy aGalaxy) {
this(aGalaxy.getMass(), aGalaxy.getName());
//no defensive copies are created here, since
//there are no mutable object fields (String is immutable)
}
/**
* Alternative style for a copy constructor, using a static newInstance
* method.
*/
public static Galaxy newInstance(Galaxy aGalaxy) {
return new Galaxy(aGalaxy.getMass(), aGalaxy.getName());
}
public double getMass() {
return fMass;
}
/**
* This is the only method which changes the state of a Galaxy
* object. If this method were removed, then a copy constructor
* would not be provided either, since immutable objects do not
* need a copy constructor.
*/
public void setMass( double aMass ){
fMass = aMass;
}
public String getName() {
return fName;
}
// PRIVATE /////
private double fMass;
private final String fName;
/**
* Test harness.
*/
public static void main (String... aArguments){
Galaxy m101 = new Galaxy(15.0, "M101");
Galaxy m101CopyOne = new Galaxy(m101);
m101CopyOne.setMass(25.0);
System.out.println("M101 mass: " + m101.getMass());
System.out.println("M101Copy mass: " + m101CopyOne.getMass());
Galaxy m101CopyTwo = Galaxy.newInstance(m101);
m101CopyTwo.setMass(35.0);
System.out.println("M101 mass: " + m101.getMass());
System.out.println("M101CopyTwo mass: " + m101CopyTwo.getMass());
}
}
There are two popular approaches. One is to provide a clone method as you mentioned, like so.
public class C implements Cloneable {
#Override public C clone() {
try {
final C result = (C) super.clone();
// copy fields that need to be copied here!
return result;
} catch (final CloneNotSupportedException ex) {
throw new AssertionError();
}
}
Pay attention to the "copy fields ... here!" part. The initial result is only a shallow copy, meaning that if there's a reference to an object, both the original and result will share the same object. For example, if C contains private int[] data you'd probably want to copy that.
...
final C result = (C) super.clone();
result.data = data.clone();
return result;
...
Note that you don't need to copy primitive fields, as their content is already copied, or immutable objects, as they can't change anyways.
The second approach is to provide a copy constructor.
public class C {
public C(final C c) {
// initialize this with c
}
}
Or a copy factory.
public class C {
public static C newInstance(final C c) {
return new C(c);
}
private C(final C c) {
// initialize this with c
}
}
Both approaches have their respective properties. clone is nice because its a method, so you don't have to know the exact type. In the end, you should always end up with a "perfect" copy. The copy constructor is nice because the caller has a chance to decide, as can be seen by the Java Collections.
final List c = ...
// Got c from somewhere else, could be anything.
// Maybe too slow for what we're trying to do?
final List myC = new ArrayList(c);
// myC is an ArrayList, with known properties
I recommend choosing either approach, whichever suits you better.
I'd use the other approaches, like reflective copying or immediate serializing/deserializing, in unit tests only. To me, they feel less appropriate for production code, mainly because of performance concerns.
Some options:
You can implement Cloneable for your object and put clone() method as public. See full explanation here: http://www.cafeaulait.org/course/week4/46.html
However, this produces a shallow copy and might be not something you want.
You can serialize and deserialize your object. You will need to implement Serializable interface for the object and all its fields.
You can use XStream to perform serialization via XML - you won't have to implement anything here.
For test code Serialization is maybe the safest answer, especially if the object is already Serializable try Apache Commons SerializationUtils for an implementation.
You can use org.apache.commons.lang3.SerializationUtils class for object cloning,
- Class should implement Serializable interface.
ClassName copyobject = SerializationUtils.clone(classobjectTocopy)
SerializationUtils.clone is also supported on Google App Engine instance
Joshua Bloch has some interesting things to say about cloneable. Depending on the size/construction of the object, I'd add a copy constructor to the object, or serialise/deserialise using one of the solutions mentioned above.
There are multiple ways to copy object in java(shallow or deep).
This Answer will help you.
Related
I'm new to Java and is trying to learn strategy for defining immutable objects via Java tutorial Oracle. Due to my limited knowledge and probably how it was worded, I'm really struggling to understand the paragraph below, I was just wondering if anyone could kindly explain to me what it actually means. Thanks in advance for any help!
Don't share references to the mutable objects. Never store references
to external, mutable objects passed to the constructor; if necessary,
create copies, and store references to the copies. Similarly, create
copies of your internal mutable objects when necessary to avoid
returning the originals in your methods.
Don't share references to the mutable objects
public class A {
private List<Integer> privateRef;
private int privateVal = 0;
public List<Integer> bad() {
return this.privateRef;
}
public int good() {
return privateVal;
}
}
The bad() method is bad because it exposes a reference to the private member, thus enabling a caller to do this:
A a = new A();
List<Integer> extractedRef = a.bad();
extractedRef.add(1);
Thus mutating a's private list (if you inspect a.privateList, you'll see that it contains 1). A no longer controls its internal state.
The good() method is good because even if a caller does:
A a = new A();
int number = a.good();
number++;
Even though number is 1, the value of a.privateVal remains 0.
Never store references to external, mutable objects passed to the constructor
Imagine we add this constructor to our class:
public class A {
...
public A(List<Integer> anotherList) {
this.privateRef = anotherList;
}
...
}
We're in a similar situation: mutations to the private list may happen externally:
List<Integer> list = new ArrayList<Integer>()
A a = new A(list);
list.add(1);
We have mutated a's internal state (if you inspect a.privateList, you'll see that it contains 1).
if necessary, create copies, and store references to the copies.
That is, if you wish A to be immutable, you should do this:
public A(List<Integer> anotherList) {
this.privateRef = new ArrayList<>(anotherList);
}
This way the new instance of A gets a copy of the list upon creation which becomes part of its internal state. From this point, mutations to the given list ("list" in the example) don't affect a's internal state: only a can mutate its private list.
Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.
This is how you'd solve the first example, if A wants to expose its internal mutable list it should not do this:
public List<Integer> bad() {
return this.privateRef;
}
but
public List<Integer> better() {
return new ArrayList<>(this.privateRef);
}
At this point
A a = new A();
List<Integer> extractedRef = a.better();
extractedRef.add(1)
At this point, a.privateRef is still empty (so its state is protected from external mutation). But extractedRef will contain 1.
An additional point. Note that even though this class applies all the principles above:
public class A {
private List<Integer> privateRef = new ArrayList<>();
private int privateVal = 0;
public A(List) {
this.privateRef.addAll(this.privateRef);
}
public List<Integer> getList() {
return new ArrayList<>(this.privateRef);
}
public int getVal() {
return privateVal;
}
public void mutate() {
this.privateVal++;
this.privateRef.clear();
}
}
(It doesn't expose references to mutable objects, nor keep references to external mutable objects), it is not really immutable as there is a way to mutate its internal state (call mutate() on it).
You can of course remove mutate(), but a more correct alternative for immutability could be:
public class A {
private final List<Integer> privateRef = new ArrayList<>();
private final int privateVal = 0;
public A(List) {
this.privateRef.addAll(this.privateRef);
}
public List<Integer> getList() {
return new ArrayList<>(this.privateRef);
}
public int getVal() {
return privateVal;
}
}
(I haven't compiled the examples, but they should be almost ok).
Practically it says you don't want to expose your state to outside world, so outside world could modify your internal state as it wants. You don't want this because it's your business in that internal state, and someone could alter it. That's also why it recomands to create copies of you internal mutable object and pass them outside as copies. They will alter those copies, but will not have side effect on your internal state.
Example:
/**
* A simple mutable.
*/
class Mutable {
private int n;
public Mutable(int n) {
this.n = n;
}
public int getN() {
return n;
}
public void setN(int n) {
this.n = n;
}
#Override
public String toString() {
return "Mutable{" + "n=" + n + '}';
}
}
// A thing that holds things.
class Thing<T> {
T m;
public Thing(T m) {
this.m = m;
}
public T getM() {
return m;
}
#Override
public String toString() {
return "Thing{" + "m=" + m + '}';
}
}
public void test() {
// Never store references to external, mutable objects passed to the constructor
Mutable m = new Mutable(10);
// t10 holds a reference to my mutable `m`, currently containing `10`
Thing<Mutable> t10 = new Thing<>(m);
// Now `m` holds `50`, even the one in `t10`.
m.setN(50);
// Make the new one holding `m` at value `50` now.
Thing<Mutable> t50 = new Thing<>(m);
// Both print the same because they both hold the same `m`
System.out.println("t10 = " + t10 + " t50 = " + t50);
// We can even mess with it after the fact - this is why you should return a copy.
t50.getM().setN(42);
// Both print the same because they both hold the same `m`
System.out.println("t10 = " + t10 + " t50 = " + t50);
}
This demmonstrates all three of the points made.
If you pass a mutable to a constructor and hold that mutable in the state, a change to that mutable will change the state of the object.
If you return a mutable it can also be modified outside your object, thus changing your state.
To avoid this:
If possible, use immutable in all cases.
If you must use a mutable in your constructor, take a copy of it if possible.
If you return the mutable anywhere, return a copy if possible.
While creating Immutable object, if there are mutable fields like Date object then following lines applies:
Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.
The same can be achieved as follows :
Create a defensive copy of the Date object while creating immutable object.
Do not provide any setter methods for this Date Object.
If at all you need to provide getter method then, getter method should return a copy of the date field since Date itself is mutable. Here, clone() method helps to achieve this.
Now, Since there is no reference to the Date field in the class, any outside this class cannot modify the state of Immutable class.
Check Example for Immutable class
I wrote the below code, and as you see, in the constructor I call some methods to perform certain operations. And now what I am inquiring about is, whether it is a good practice to call those methods from the constructor OR declare those methods as public and instantiate an object from the class info, and let the object call those methods? What is the good practice for that?
Code:
class Info {
public RoadInfo(String cityName, double lat, double lng) throws FileNotFoundException, SAXException, IOException, XPathExpressionException {
// TODO Auto-generated constructor stub
this.cityname = cityName;
this.lat = lat;
this.lng = lng;
this.path = "c:"+File.separatorChar+this.cityname+".xml";
System.out.println(path);
this.initXPath();
this.method1()
this.method2()
..
this.expr = "//node[#lat='"+this.lat+"'"+"]/following-sibling::tag[1]/#v";
this.xPath.compile(this.expr);
String s = (String) this.xPath.evaluate(this.expr, this.document, XPathConstants.STRING);
System.out.println(s);
}
TLDR In my opinion, using methods inside of a constructor is a sign of bad design. If you aren't looking for design advice, then the answer "no there's nothing wrong with it, technically speaking, as long as you avoid calling non-final methods" should do you fine. If you ARE looking for design advice, see below.
I think your example code is not good practice at all. In my opinion, a constructor should only receive values which is relevant to it and should not need to perform any other initialization on those values. There's no way for you to test that your constructor 'works' with all of those little extra steps - all you can do is construct the object and hope that everything ends up in the correct state. Further, your constructor ends up with more than one reason to change, which violates the SRP.
class Info {
public RoadInfo(String cityName, double lat, double lng) throws FileNotFoundException, SAXException, IOException, XPathExpressionException {
// TODO Auto-generated constructor stub
this.cityname = cityName;
this.lat = lat;
this.lng = lng;
this.path = "c:"+File.separatorChar+this.cityname+".xml";
System.out.println(path);
this.initXPath();
this.method1()
this.method2()
..
this.expr = "//node[#lat='"+this.lat+"'"+"]/following-sibling::tag[1]/#v";
this.xPath.compile(this.expr);
String s = (String) this.xPath.evaluate(this.expr, this.document, XPathConstants.STRING);
System.out.println(s);
}
So, for example, this constructor is loading a file, parsing it in XPath.. if I ever want to create a RoadInfo object, I can now only do it by loading files and having to worry about exceptions being thrown. This class also now becomes hilariously difficult to unit test because now you can't test the this.initXPath() method in isolation, for example - if this.initXPath(), this.method1() or this.method2() have any failures, then every one of your test cases will fail. Bad!
I would prefer it to look something more like this:
class RoadInfoFactory {
public RoadInfo getRoadInfo(String cityName, double lat, double lng) {
String path = this.buildPathForCityName(cityName);
String expression = this.buildExpressionForLatitute(lat);
XPath xpath = this.initializeXPath();
XDocument document = ...;
String s = (String) xpath.evaluate(expression, document, XPathConstants.STRING);
// Or whatever you do with it..
return new RoadInfo(s);
}
}
Never mind the fact that you have at least 5 responsibilities here.
Build OS-neutral path
Build XPath expression for latitude/longitude
Create XPath doocument
Retrieve s - whatever that is
Create new RoadInfo instance
Each of these responsibilities (Except the last) should be separated into their own classes (IMO), and have RoadInfoFactory orchestrate them all together.
The purpose of the constructor is to establish the class invariants, that is, to bring the newly created object into a state that then allows clients to use them. In general, it is bad practice for an object to be relying on extra initialisation after it's constructed. What you want to avoid is to write such things into the documentation as:
...after creating an instance of class X, remember to ALWAYS call
initX(), or bad things will happen!
Though in certain cases it's difficult to avoid it and the constructor can become quite messy. For example loading external files in a constructor is problematic.
In these cases there are two things you can do:
Rewrite your constructor so it requires the contents of the file instead of the name. Let the caller do the loading. The main difference is that you require the caller to do something before the object is created, and you can express it with the signature of your constructor: public RoadInfo(String cityName, Document cityDatabase, double lat, double lng) {...} Of course you can go even further and require the value of s straight away and let the caller do the XPath search. Note that all these steps move the class towards having a single responsibility, which is considered a good thing.
But now you require the caller to perform many steps before they can build your RoadInfo. This is where you can use factories, which perform this extra initialisation too and return fully built RoadInfo objects.
The most important thing though is that the constructor must not call any method of the object under construction that can be overridden. Calling private methods is fine, calling public methods on this is not a good idea unless the methods or the class itself is marked as final.
If you call such a method, there's always a chance that the class overriding the method does something that breaks your functionality, like exposing this to the outside world before the construction is completed. Here's an example:
public abstract class Foo {
public Foo(String param) {
if (this.processParam(param) == null)
throw new IllegalArgumentException( "Can't process param.");
}
protected abstract processParam(String param);
}
public class Bar extends Foo {
public Bar(String param) {super(param);}
protected processParam(String param) {
SomeOtherClass.registerListener(this); // Things go horribly wrong here
return null;
}
}
If you now call new Bar("x"), the constructor of Foo will throw an exception because it considers the parameter invalid. But Bar.processParam() leaked a reference of this to SomeOtherClass, potentially allowing SomeOtherClass to use the Bar instance that shouldn't even exist.
More typically, classes requiring heavy initialization would be provided to the client via a factory method. Constructors are often too restrictive—a random example being the inability to surround the super or this opening call with try-catch.
If you provide a public factory method, you can make the constructor private. The constructor can only do the easy work like assigning final fields, and the factory takes over. In the long run this is a more future-proof design. Many public libraries had to break their earlier API to introduce factories that allow their code to grow.
Is it a good practice to call some methods from the constructor?
Sadly the only good answer to this is It depends on the object.
If the object is intended to hold information then the answer must be probably not, try to avoid it because an object should really only do one thing.
If, however, the object is there to perform a function then by all means make sure that it is ready to perform that function by calling methods etc. If, for example it is a database connection then you might wish to connect to the database at construct time, or at least register itself in a connection pool.
It is, however, good practice to postpone any potentially slow stuff you can postpone until you need it. In my example of the database you may wish to postpone the actual connection to the database but you would certainly register the connection in the connection pool.
Sadly - the answer to the opposite question:
Is it a bad practice to call some methods from the constructor?
Is also It depends on the object for similar reasons.
There's no good practice, just bad practice that you should not do.
When you call a method within a constructor, some dangerous here are:
1) the method can be overwritten, and its subclass implement break your class's constraint protected by constructor, the implement is out of your control.
class T {
int v;
T() {
v = getValue();
}
int getValue() {
return 1;
}
}
class Sub extends T {
#Override
int getValue() {
return -1;
}
}
here T's v suppose to be 1 when you call new T(), but when you create a new Sub(), 'v' will be set to -1, which may break T's constraint, and this happens unconsciously.
2) the half-constructed object leaked, while it's status may be illegal.
class T {
int a, b;
T(C c) {
// status of "this" is illegal now, but visible to c
c.calc(this);
a = 1;
b = 2;
}
}
class C {
int calc(T t) {
return t.a / t.b;
}
}
3) something more I don't know...
if you can prevent all of them, you can do what you want.
(Try to keep exceptions not thrown. So the constructor can nicely initialize a field.)
Do not call overridable methods in the constructor.
About the pitfalls of an overridable method call in a constructor:
The evaluation of a (child) constructor is:
"Zero" all fields (0, null, 0.0, false)
Call the super constructor (implicit if not in code)
Call all field initializations (field declarations with = ...)
Do rest of constructor code
So:
class A {
A() { f(); }
protected void f() { }
}
class B implements A {
String a;
String b = null;
String c = "c";
B() {
//[ a = null, b = null, c = null; ]
//[ super();
// B.f();
//]
//[ b = null; ]
//[ c = "c"; ]
// "nullA" - null - "c"
System.out.printf("end %s - %s - %s%n", a, b, c);
}
#Override
protected void f() {
System.out.printf("enter f : %s - %s - %s%n", a, b, c);
// null - null - null
a += "A";
b += "B";
c += "C";
// "nullA" - "nullB" - "nullC"
System.out.printf("leave f : %s - %s - %s%n", a, b, c);
}
}
That behavior is quite muddying the waters, and here doing assignments that are immediately overwritten by field initializations.
A normal call one often sees in constructors is a setter, that maybe has some normalization code. Make that setter public final void setX(X x);.
I have been working to upgrade my Java code baseline so that it follows good security practices and have run into an issue related to generics. Say you have the following:
public class SomeClass<T>
{
private T value;
public T getValue()
{
return value;
}
public void setValue(T value)
{
this.value = value;
}
}
I have not found a good answer on how to edit these methods so that value does not leak like it does in this example class for a generic object that does not implement Clonable and in some cases has no default constructor.
As I understand it, you want to make sure that nothing outside SomeClass can mutate the object value.
In C++, you could returns a const reference (avoid copying altogether), but Java does not have that. So let's look at copying...
First, know that some objects cannot be copied. For example, stream, gui elements, etc. Thus, trying to copy all objects is a hopeless endeavor from the start.
But what about objects that are copiable?
In Java, you cannot call the copy constructor (or any other constructor) of a generic (Calling constructor of a generic type).
There is the Cloneable interface, but that is really nothing more than a promise that clone works; it does not actually expose clone publically. Thus, for generics, you have to use reflection, as shown here.
Unfortunately, there is no good solution. The only viable one (except for changing the purpose or semantics of your class) is to use the clone method as shown in the link above, and realize that some objects cannot be copied.
Ultimately, the best thing to do is find a solution that does not require this. Make a (non-generic) read-only wrapper class that exposes the non-mutating methods. Or stipulate in documentation that mutating methods must not be called.
I can see three approaches:
Make copies. This of course would only work with types can can be copied (and that you know how to copy).
Only support immutable types.
Remove getValue(). Instead, provide methods that operate directly on this.value without exposing it outside the class. In this approach, setValue() can still be problematic (you need to make sure that the caller does not hold on to the object reference after calling setValue()).
If T can be arbitrary type that you have no control over, then options 1 and 2 won't be suitable.
I believe that i undestand you ... If you want to restrict a generic type you should use extends keyword that in generic type is not equals to general class. If you use only the class how implements Clonable are able to instantiate this class. One example:
public class Stack {
public static void main(String[] args) {
SomeClass<Animal> sc = new SomeClass<>(); //This generate an error because doesnt implements Clonable interface
SomeClass<Person> sc1 = new SomeClass<>();
}
}
class SomeClass<T extends Comparable> //Note that extends means implements or the common extends
{
private T value;
public T getValue()
{
return value;
}
public void setValue(T value)
{
this.value = value;
}
}
class Person implements Comparable<Person>{
#Override
public int compareTo(Person p){
return 0;
}
}
class Animal {
}
I wish i helped you.
:)
An object whose state is encapsulated in a mutable object should generally never expose to the outside world any reference to that object, and should avoid giving the outside world a reference to any mutable object (even a copy) which claims to encapsulate its state. The problem is that given code:
Foo foo = myEntity1.getFoo();
foo.bar = 23;
myEntity2.setFoo(foo);
foo.bar = 47;
myEntity3.setFoo(foo);
there is no clear indication whether or how the change to foo.bar would affect the various entities. If the code had instead been:
Foo foo = myEntity1.getFoo();
foo = foo.withBar(23); // makes a new instance which is like foo, but where bar==23
myEntity2.setFoo(foo);
foo = foo.withBar(47); // makes a new instance which is like foo, but where bar==47
myEntity3.setFoo(foo);
it would be very clear that the bar property of myEntity1's foo will be unaffected, that of myEntity2 will be 23, and that of myEntity3 will be 47. If foo is a mutable class, the pattern should be:
Foo foo = new Foo();
myEntity1.writeTo(foo); // Copy properties from myEntity1 to the supplied instance
foo.bar = 23;
myEntity2.readFrom(foo); // Copy properties from the supplied instance to myEntity2
foo.bar = 47;
myEntity2.readFrom(foo); // Copy properties from the supplied instance to myEntity3
Here, myEntity1 isn't giving the caller an object, but is instead copying data to an object supplied by the caller. Consequently, it's much clearer that the caller shouldn't expect the writes to foo.bar to affect the entities directly, but merely change what will be written in subsequent readFrom calls.
I am totally confused with ArrayList behavior. Wrote really long post, then realized no one is going to analyse huge code, so just core of the problem. Numbers are for convenience, but in my app these 0 and 24 are dynamic values.
ArrayList<VoipBlock> sortedBlocks = new ArrayList<VoipBlock>();
VoipBlock vb3 =new VoipBlock();
vb3=sortedBlocks.get(0);
vb3.setPacketNumber(24);
Essentially my final aim is to: modify and add back to arrayList as new value. However when I do that the guy at position 0 in ArrayList -> unsortedBlocks.get(0); replicates all the changes done to vb3 which of course is not what I want. I want vb3 acquire same values as VoipBlock inside of ArrayList, but I want it to be detached.
This is yet another case of passing by reference. I hate technical explanations - Java passes everything by value, BUT in some cases it passes references by values - this is same as saying not-oily oil. Please help.
It reminds me my start of learning JavaScript - I hated the language - until I watched proper materials at lynda.com - JavaScript Good Practices? - Diagrams killed me. It is the lazy description that turns us-youth away from brilliant technology, not the technology itself.
Please don't let it bother my stress and don't be in any way offended by me, it is just general complaining, maybe someone will look at it and make life better :-)
Thanks for Your time,
Desperately awaiting for help :-)
To achieve your objective you can use clone method. you have to override this method in VoipBlock class
Lets say VoipBlock is as follows
public class VoipBlock {
private int packetNumber;
private String type;
public int getPacketNumber() {
return packetNumber;
}
public String getType() {
return type;
}
public void setPacketNumber(int value) {
packetNumber = value;
}
public void setType(String value) {
type = value
}
public VoipBlock clone() {
VoipBlock clone = VoipBlock();
clone.setType(this.getType());
clone.setPacketNumber(this.getPacketNumber());
return clone;
}
}
So, using the same code you can do like as follows
ArrayList<VoipBlock> sortedBlocks = new ArrayList<VoipBlock>();
VoipBlock vb3 =new VoipBlock();
sortedBlocks.add(vb3);
vb3=sortedBlocks.get(0).clone();
vb3.setPacketNumber(24);
Note that upon calling clone method in above code segment, vb3 get assigned with a new VoipBlock instance. And already inserted VoipBlock to the array remains unchanged.
if you are looking to have kind of sample instances of VoipBlock instances which you later wanted to use in creating similar instances like them. check on immutability/mutability aspect of the code. check "Effective Java" by Joshua Blouch
The following will always copy the reference of b to a:
AnyClass a = ...;
AnyClass b = ...;
a = b;
What you want is probably to clone the object:
a = b.clone();
If I understand correctly, you're a bit unsure about how references and values work. I think the rule of thumb is that primitive types like int, char, boolean and maybe String are copied but Objects just have their reference passed.
The line vb3=sortedBlocks.get(0); completely replaces whatever vb3 used to be with the first thing in the ArrayList. And yes, it won't be a copy, it will be a reference to the same object in memory. So whatever you do will affect both of them. You need to either manually copy over all the information you need or to use a clone() or copy() function.
So for example, in your code, the line VoipBlock vb3 =new VoipBlock(); is a bit redundant because you're overwriting the new instance straight away.
What you really need here is to either use a copy constructor or declare VoipBlock to be Clonable so you can use the clone() method.
What you are interpreting as passing by reference is not actually passing by reference. Java objects are really pointers. Because of this you are passing the value of the pointer. So when you do:
vb3=sortedBlocks.get(0);
you are really assigning vb3 to point to the same locations in memory as sortedBlocks.get(0). Therefore when you manipulate vb3 properties through their setters, the result is seen in both.
If you want two separate pointers you need to use the new keyword or use the clone() method which does this under the hood.
An example to prove this is:
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
public class Main {
public void doSomething(Person p) {
p = new Person("Bob");
System.out.println(p.getName());
}
public static void main(String[] args) {
Person p = new Person("Billy");
System.out.println(p.getName());
doSomething(p);
System.out.println(p.getName());
}
}
Since Java is pass by value the output will be: Billy, Bob, Billy. If Java were pass by reference it would be Billy, Bob, Bob. If I did not do the new Person in the doSomething() method and instead used the setName() method I would end up with Billy, Bob, Bob also but this is due to the fact I'm now modifying off the same pointer not that I passed by reference as the example above proves that's not the case.
Normally when I deep copy objects I use a copy constructor. For our assignment we are supposed to make an ObjectList, even though the instructor noted that such a list is unwise to use. Anyways, I've run into an issue when I am adding a new Object to the array. I am trying to create a deep copy of the Object before adding it to the array to prevent a privacy leak, but there is no copy constructor for the Object class. For example, the following does not work:
Object temp = new Object(insertObjectArgument);
I then looked into Object.clone(), but it looks like I should stay as far away from that as possible.
Is there some way I can deep copy an object of type Object?
For complicated objects and when performance is not significant i use a json library, like gson
to serialize the object to json text, then deserialize the text to get new object.
gson which based on reflection will works in most cases, except that transient fields will not be copied and objects with circular reference with cause StackOverflow exception.
public static <ObjectType> ObjectType Copy(ObjectType AnObject, Class<ObjectType> ClassInfo)
{
Gson gson = new GsonBuilder().create();
String text = gson.toJson(AnObject);
ObjectType newObject = gson.fromJson(text, ClassInfo);
return newObject;
}
public static void main(String[] args)
{
MyObject anObject ...
MyObject copyObject = Copy(o, MyObject.class);
}
Java has no 'magic' utility for deep copying. If the objects you are concerned with are of classes that chose to support clone(), you can use clone. However, without reading all the code, it's impossible to be sure that the implementations of the clone methods will satisfy your security requirements. Otherwise, you have to do it the hard way, building a new object graph from the old one.
You need to make a method called clone and override it for the typical clone() method that comes with the Object class using #Override. After this, make a new object, and copy the data from the old object into it. Where I put /... means that more code can be added or you can take away the code I originally put.
/**
* Explanation for http://stackoverflow.com/questions/35120424/how-to-deep-copy-an-object-of-type-object
*
* #author Riley C
* #version 1/31/16
*/
public class ObjectToReturn
{
//variables
int x;
int y;
// ...
//constructor
public ObjectToReturn()
{
x = 0;
y = 0;
// ...
}
//overrides
#Override
public ObjectToReturn clone()
{
ObjectToReturn returnMe = new ObjectToReturn();
returnMe.setX(this.x);
returnMe.setY(this.y);
// ...
return returnMe;
}
//methods
public void setX(int x) {this.x = x;}
public void setY(int y) {this.y = y;}
// ...
public int getX() {return x;}
public int getY() {return y;}
// ...
}
Why you shouldn't use the default clone
From what I can remember, while clone() can sometimes generate a deep copy of an Object, it doesn't always do it.
Habits to get into
Good habits my college instructor said his company liked to see if making sure you make deep copies of arrays and objects, as well as overriding the equals, clone, and toString method which typically come with the class Object. This will allow you to use these methods on your objects with how you would like them to work, instead of the default values which may give answers that make no sense. It also is often cleaner, and is prone to throw less errors.