References objects in Java [duplicate] - java

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 9 years ago.
I have a doubt about object references in Java. It always send its object by reference to the functions, and it means that if you modifie them in the function sent, they will come back modified.
A solution for this would be copying the object before the send. But for that, do I have to create a copy function in the object class? Or is any other alternative? Thanks

I typically add a copy constructor for this kind of scenario like so:
public class MyObject {
//members
public MyObject(MyObject objectToCopy) {
this.member = objectToCopy.member;
//...
}
}
Then you can just make a new object with a simple one liner.
public void DoWork(MyObject object) {
MyObject copy = new MyObject(object);
//do stuff
}

Java is always pass-by-value. What you are describing is passing the object reference by value.
There is a key distinction here. You are not passing the object as a reference, so the reference link is broken as soon as you assign a new instance to your parameter. As long as the reference value remains the same, altering the contents of an object passed in will persist when you return back to the caller. Another key difference is that a reference value can be null... but null is not an object - so how can you reference the absence of an object?
If you want to create a new object, you will need to copy the existing one. The copy should be performed inside the method to ensure the operation is consistent.
For simple objects (objects with a shallow class hierarchy, like the example below), you can usually get by with a basic copy constructor:
class Album {
private String title;
private String artist;
public Album(Album copy) {
this.title = copy.title;
this.artist = copy.artist;
}
}
This will allow you to copy the object inside your method:
public void copyAlbum(Album album) {
album = new Album(album); // Clone the album passed in
}
For more complex object graphs, you may want to use a library such as Orika or Dozer to accurately create a deep copy of your object. This question has some useful advice on copying objects in Java.

You should create a copy constructor for each object yourself. The reason is simple: if A references B and you want to copy A, would you copy the reference to B or the whole referenced B object? This question must be answered for each case individually, so there is no general solution.

It is true that you send the object, and changes will be done to the referenced object. There is no easy "native" way to copy objects in Java, but you can copy objects by using frameworks such as Dozer:
http://dozer.sourceforge.net/

Related

Initialize one object to another in java [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 10 months ago.
What happens when I initialize one object to another in java? Is the reference of that object copied in new object or is a new object created with same member values as in the orginal object;
A obj1=new A("apple");
A obj2=obj1;
What is the correct interpretation for this scenario?
when I initialize one object to another in java
I do not know what you mean by "to another". But you initialized only a single object.
First line
Regarding your first line:
A obj1=new A("apple");
A obj1 declares a reference variable, giving it a name obj1, and specifies that this var will hold a reference to any object of type A. This reference variable is initially null.
Calling new A("apple") constructs an object some place in memory. The result, the return value, of this code is a reference to the new object.
The = assigns that reference to be the content of the variable named obj1.
You can think of a reference variable as containing the address in memory where the beginning of that object's block of allocated memory resides. In Java we never see the literal contents of a reference variable. But we know we can reach the object via that reference variable.
In our daily work of programming in Java, we may generally think of obj1 as being the object. But actually obj1 is a way to find the object, a tether attached to the object, a line we can follow to access the object somewhere else in memory.
Second line
Regarding your second line:
A obj2=obj1;
First you declare a new variable named obj2 to hold a reference to an object of type A. Then you copied the reference from obj1 and put that copy into obj2.
You are left with:
A single object.
Two references to that single object.
It is just the reference coppied, not an actual new object in some other memory space.
Normally for deep-copy you can declare yourself a clone method in that class that uses the properties of the passed object and creates another object with new keyword and returns it. This way you will have a new object when you use clone method. More specifically you can declare your class to implement Cloneable interface and then provide an override implementation for the method clone() which already exists in parent Object class.
For shallow-copy you should again create a clone method in your class and in this method you can just use return super.clone() so that the default clone() method provided by Object class will be used to make a shallow-copy of the object meaning only primitive fields will be actually copied and for any non primitive fields the reference will be copied instead.
For your simple example where the field in this class is only some String you can use the shallow copy of clone already provided by Object class and this will seem enough.
If however you had more non primitive fields in this class, then you will had to override your clone method and provide some implementation so that a deep copy could be returned.

How to define a "good" get() method for a private variable in a class? [duplicate]

This question already has answers here:
Why make defensive copies in getters inside immutable classes?
(7 answers)
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 3 years ago.
I'm learning Java and I have some doubts.
If defined a class with a private variable like
class test<A>{
private A var;
...
public A get(){
return var;
}
}
Is the get method wrong?
I think so because with this definition I can modify the variable "var" like
test<A> x = new test<A>();
A temp = x.get();
temp.set(*something*);
At the end x is changed (I tested it using Vector as A). If I understand correctly, this works because object reference (I miss C pointers, sob). Am I wrong? Maybe I don't understand the purpose of the keyword "private"! Thanks in advance!
Edit: I have no problems with "pass-by-reference" and "pass-by-value". I have doubts defining get() method for a private variable in a class (you don't say?). Please stop linking Is Java "pass-by-reference" or "pass-by-value"?
If your getter method is returning a reference to a mutable object, then this greatly weakens the quality of the encapsulation provided by your class, because it becomes possible to modify the state of an instance of your class without calling a method of the class.
One standard strategy to guard against this problem is what J. Bloch calls defensive copies (Effective Java, 3rd edition, Item 50: "Make defensive copies when needed").
This would mean creating a copy of var in the getter method, and returning that copy instead. How to do this depends on the design of A.
Because A is a type parameter, making a copy of the instance requires additional support in the design. To see how to achieve this using Java's cloning mechanism, see my answer to the post "Does it make sense to create a Copyable type interface instead of using Cloneable?".
If this is a problem, you can create a façade to protect your variable
public class Facade extends A {
A myObj;
public Facade (A obj) {
myObj =
}
public A get(){
return myObj.get();
}
public B set(Object val) {
throw new RuntimeException("Setting is not allowed");
}
}
This might be a bit too much detail for just starting, but you might review class java.util.concurrent.atomic.AtomicReference<V>, which is very similar to your example.
Generally speaking, placing instance variables in private variables, while providing access to the variable using a getter and a setter, is standard practice.
Note that your class name should be capitalized, type parameter 'V' is more standard, and the variable name would more usually be 'value'. Also, try to pick a more communicative name for the class. (Type parameter type variable could be 'ValueType', which would fit some preferences. But, single character type variable names are more usual.)
public class Wrapper<V> {
private V value;
public V get() {
return value;
}
public void set(V value) {
this.value = value;
}
}
I'd add some other point here: as others have said, you hand out the object reference and it can be modified, which could be bad.
Object orientation is about keeping the data and the code that works on it in one place. If you need getters, think what the callers of the getters need to do, and whether that action should rather be a method on the class that has the data. Your code could suffer from the Feature Envy code smell, as it violates the Tell, Don't Ask principle.
To fix this, remove the getter, and introduce new methods as needed. For example, if you have some data object that needs to get printed, you could pass the Printer to the object and have it print itself to the given Printer.
If you're dealing with a collection class (just a guess from your template parameter), you may need to keep the getter, but then you're probably not concerned with the caller changing the value anyway.

Java LinkedList.get() does not return deep copy? [duplicate]

This question already has answers here:
Java: recommended solution for deep cloning/copying an instance
(10 answers)
Closed 8 years ago.
I have a question about using a LinkedList and the .get() operation. Java as I understand passes objects by reference, so if I have a linked list called A, and I do temp B = A.get(i), I retrieve an object B that I can modify and the changes are reflected in A.get(i).
However, if the object B has within it (Say another LinkedList object), I do not get a deep copy correct? Is the solution that I must create a copy constructor for my class 'temp' in this example. Or is there a better, built-in way to do this?
Thanks for your help.
Java as I understand passes objects by reference..
No. Java pass everything by value. If you have a reference type, the reference is passed by value. See this question.
if I have a linked list called A, and I do temp B = A.get(i), I retrieve an object B that I can modify and the changes are reflected in A.get(i).
If you have a list of reference types get(i) will return a reference to a particular instance. The element in the list and your retrieved reference will refer to the same object. So if you change the object in some way, it will be "visible" from both references.
However, if the object B has within it (Say another LinkedList object), I do not get a deep copy correct?
Correct. You get a reference.
Is the solution that I must create a copy constructor for my class 'temp' in this example. Or is there a better, built-in way to do this?
If you need a deep copy of your object, you must implement it yourself.
Java as I understand passes objects by reference
No. It passes references by value. It doesn't pass objects at all [except in the case of RMI.]
so if I have a linked list called A, and I do temp B = A.get(i), I retrieve an object B
No. You retrieve a reference that refers to B. The same B whose reference you passed when you added it to the list.
that I can modify and the changes are reflected in A.get(i).
Yes, see above.
However, if the object B has within it (Say another LinkedList object), I do not get a deep copy correct?
Correct. Just like the first case. No difference whatsoever.
Is the solution that I must create a copy constructor for my class 'temp' in this example.
Solution to what? I've never used a copy constructor or the clone() method in Java since 1997. What problem are you trying to solve?
Or is there a better, built-in way to do this?
To do what?
It does not return a "deep copy" because there is no copying done at all, at least, not at the object level. Let me explain.
When you have an instance of an object, the variable that references that object is a pointer to the object. The object can be referenced and modified by many variables (pointers). Observe the following code:
// Let's assume I have a custom object class called Student
// Here the object is created and s now points to the new Student object
Student s = new Student();
// Here I create another variable that points to the same object
Student s2 = s;
Those two variables both point to the same object and any changes that one variable makes to the object will then be reflected in the other.
This ties into your list example. If you have a LinkedList of objects, it is actually a list of pointers to objects. So calling get(2) on the list will get a reference to the 3rd object in the list. The object that it's referencing is the object, not a copy. So any references, variables, methods etc. that were in this object will still be there.
I hope that answers your question :)

What is the advantage of creating object with clone() over constructor?

Whenever I'm doing shallow cloning then if my class consists of any user-defined reference type then there reference value will copied but not values, but if I'm writing String s="something", then even though s is an object but it is directly copied into the cloned object, why so? Does it mean pre-defined object will be copied but user-defined object reference will be copied?
If you want an object of the same state, then you can use clone(). If there's no difference between the two I would say use a constructor. Cloning requires an object to already have been made in order to make another instance, not to mention the implementation of Cloneable is already fairly messy.
Also note, the object you attempt to use clone() on must actually implement Cloneable and override the method in order to actually work.
It is not that "predefined" object types are deep copied and "user defined" object types are shallow copied.
Your cited example is this :
String s = "something";
Yes, a string literal is an "object" but strings are immutable objects, and more importantly they are special down to the level that they are built into the design of the language itself. REALLY what you are doing here is nothing different from saying YourClass varName = new YourClass(); Here, you create a new String object with value "something" (if the literal does not exist in the string constant pool) and store a reference to that object to your variable s of type String.
You can shallow copy a string just like you can shallow copy a user defined object:
String s = "something"; //in this example this would be the same as saying new String("something")
String imAShallowCopyOfS = s;
System.out.println(imAShallowCopyOfS == s); //true
You are still just copying the reference that s points to into imAShallowCopyOfS. I would suggest you shy away from using Strings to learn the behavior of references in java, though, as they are rather special objects that receive some special treatment by the compiler/vm.

Getting a copy of an object

I don't fully understand when Java passes a copy/value and when it passes a "reference" (the pointer).
I'm trying to assign a copy of a static object I have, but I'm not sure how to go about it.
I have this:
static ArrayList<MyObject> myObjects;
I want to get a copy of myObjects so that I can play around with the values without affecting the original. Does it pass a reference or a copy/value when I use a getter like so:
public static ArrayList<MyObject> getMyObject()
{
return ThisClass.myObjects;
}
What does that return? If it's a reference, how can I get a copy?
I've seen these:
(How do I copy an object in Java?)
(Java: getter method vs. public instance variable: performance and memory)
(Is Java "pass-by-reference" or "pass-by-value"?)
(How can Java assignment be made to point to an object instead of making a copy?)
But I still don't quite understand what I'll get back.
Java will always return a reference and not a copy as long as it's not a primitive type (aka long,int,short,etc or one of the primitive wrappers Long,Integer, Short.
To get a copy you will need to either copy the data, use a copy constructor, or use the method clone which will create a new object with the appropriate values.
Example of a copy constructor with a list, by default this is a "shallow copy" meaning the objects inside are the same.
List<MyObject> myNewCopiedList = new ArrayList<MyObject>(oldList);
For a "deep copy", meaning the objects inside can be mutated without affecting the originals you will need to make a new List then add copies/clones of the object and add.
Example, assuming MyObject has a copy constructor or a clone method.
List<MyObject> myNewCopiedList = new ArrayList<MyObject>();
for (MyObject myo : oldList){
myNewCopiedList.add(new MyObject(myo)); // if there is a copy constructor
myNewCopiedList.add(myo.clone()); // if there is clone method
}
Think of it this way. Java is always pass by value.
For primitives, it is pass by value(actual value).
For objects, it is pass by value-of-reference.
public int square(int a) { //The parameter a is copy of actual int itself.
//So now there are 2 ints
a=a*a; //Only local copy a is actually modified.
//The integer variable passed(in caller function) is not modified.
return a;
}
If you call doSomething(d) where d is an object, a copy of reference pointing to this object is assigned to parameter a but there is only one object.
public void doSomething(Object a) {
// Here the parameter is a reference which points to an
// object, not the object itself
a.doMore(); //But doMore() does things using a different ref but on the same object.
//The object can be modified!
Object b = new Object();
a = b; //Object referenced by passed parameter does not change but
//copy of reference now points to different object.
// Now there is no reference of original object passed in this method.
}
Technically, Java is always pass-by-value. However, for a beginner's thinking, it's easier to think about it this way:
If it's a primitive type, it's pass-by-value.
If it's an object, it's pass-by-reference.
So in your example, you are returning a reference to the same static object in ThisClass. The reason I say this is technically pass-by-value is because your variable myObjects actually stores the memory address of the ArrayList<MyObject> which you declared, and it's this which is passed.
In order to properly make a copy of an object, one must know which non-primitive fields encapsulate
Mutable aspects of the object's state, but not its identity
The identity of an object and other immutable aspects, but no mutable aspects.
Aspects of the object which are expected never to be exposed to any code which might mutate them (and not identity)
Mutable aspects of the object's state, as well as its identity
Based upon what a field encapsulates, a correct copy of Foo
If one of Foo's field which encapsulates mutable state, a the corresponding field in a copy of Foo should hold a reference to a different object with the same state.
If a field encapsulates object identity, that field in the copy must hold a reference to the same object as in Foo--not a copy.
If a field encapsulates only immutable aspects other than identity, then a copy of Foo may either hold a reference to the same object as in Foo, or any object which has the same immutable state, as convenient.
If a field encapsulates both mutable state and identity, because the first two requirements will conflict, it will not be possible to copy the object in isolation.
In some cases, it may be possible to copy a set of mutable objects which use references to each other to encapsulate both state and identity. Such a copy must be performed on the set as a whole; for each object within the set, any field which in the original object encapsulates both the mutable state and identity of another object in the original set must in the copy refer to the corresponding object in the copied set.

Categories