Make a reference immutable? - java

class Some{
private int id;
private String name;
//getters and setters
}
class Check{
private Some[] someVals;
//getters and setters
}
Assume I have populated values into the someVals in Check class
void newMethod(){
Check checkPrev = getCheckPopulated();
Some[] someFirst = checkPrev.getSomeVals();
modifySome(someFirst);
Some[] some = ? // at this point need the values of someFirst
}
My question is to get the value of the Some[] array even after the modification(where i have specified), that is the values which were first present when assigned.
fine I will make my question clear.
final Some[] someFirst = checkPrev.getSomeVals(); didnot work
Is there a small tip similar to final by preserving the arrays value without having to reassign all the values to another array all over again?

You can't have your cake and eat it also. You have to make a deep copy of the object, and then modify the original copy. Then, the deep copy will contain the original values.

In your modifySome method, return a new Some[] array.
Some[] modifySome(Some[] passedArray){
Some[] result = new Some[passedArray.length];
System.arraycopy( passedArray, 0, result , 0, a.length );
//Modify result as needed
return result
}
If you cange modifySome to return an array, your code can change to:
Some[] some = modifySome(someFirst);
After that line, someFirst will still be the same as it was before and some will be the modified values.

One option is to use a CopyOnWriteArrayList.
CopyOnWriteArrayList<Some> someFirst = checkPrev.getSomeVals();
Iterator iterator = someFirst.iterator();
modifySome(some);
The iterator will still be referring to the original list, not to the modified list.
Another option is to make a copy of the original array.
Some[] someFirst = checkPrev.getSomeVals();
Some[] someCopy = new Some[someFirst.length];
System.arrayCopy(someFirst, 0, someCopy, 0, someFirst.length);
modifySome(some);
someCopy will still hold a copy of the original array.

Welcome to the mutable world of Java beans.
You cannot do what you want to do... But here is a solution using a couple of interfaces I wrote:
// Both classes in the same package
#Immutable // by contract
class Some implements Frozen<SomeBuilder>
{
// All fields are final, package local
final String name;
// getters only -- NO setters
public Some(final SomeBuilder builder)
{
name = builder.name;
// other
}
// Return a thawed version
#Override
public SomeBuilder thaw()
{
return new SomeBuilder(this);
}
}
#NotThreadSafe // by contract
class SomeBuilder implements Thawed<Some>
{
// Mutable fields here, package local
String name;
// other
// To create a new builder
public SomeBuilder()
{
}
// Package local constructor
SomeBuilder(final Some some)
{
name = some.name;
// etc
}
// Mutations
public SomeBuilder setName(final String name)
{
this.name = name;
return this;
}
// Return a frozen version
#Override
public Some freeze()
{
return new Some(this);
}
}
Now, as to your modify function, make it return a NEW array. And use .freeze()/.thaw() to create new instances of Some from existing ones.

One of the weaknesses with Java is that there is fundamentally only one non-primitive type: the promiscuous heap object reference. There is no way that an instance of class George which holds a reference to a object Foo of class Bar outside its package can share that reference with outside code without giving that outside code the perpetual ability to do anything to Foo that George can do with it. Part of the design goal of Java is to be easy to implement even on simple hardware systems, and having a single non-primitive type helps it achieve that goal. On the other hand, it also means that the programmer is required to keep track of which object references serve to encapsulate:
Immutable aspects of object state other than identity, which cannot be changed even by code which holds a reference.
Object identity (as well as, perhaps, other immutable aspects of state)
Aspects of object state which would be mutable, except that they are expected never to be given to code that would actually mutate them, but not identity.
Mutable aspects of object state which are "owned" by the code which hold the reference, but not identity.
Mutable aspects of object state, as well as identity.
In your code, because arrays are mutable, your array-type field cannot have the first meaning, but it could hold any of the other four. In addition, the elements of the array could hold any of the above kinds of things. If you consider the state of your object to be the combination of id and name pairs held in its array, if the id and/or name of a Some to which the Check holds a reference could change, and if such a change would be considered a change in the state of the Check, then making a copy of the Check's state would require creating a new array, and populating it with new Some instances whose data is copied from the corresponding instances in the original array.
If none of the Check objects which are in the array will ever be exposed to code that might mutate them, then it would not be necessary to construct new instances of the individual Check objects; creating a new array and populating it with references to the objects in the original array would suffice. Likewise if the purpose of the array is to encapsulate the identities of Check objects which are defined elsewhere and thus changes to those objects would not be considered changes to the Check's state. Note that in the former situation (the objects never change), replacing the Some objects with new instances that hold the same data would be inefficient but would not break anything. In the latter situation (the array encapsulates the identities of the objects, rather than their states), replacing the references with references to new instances would break the code.
While many people talk about "deep cloning" or "shallow cloning", such terminology mainly stems from the lack of clarity about what various object references are supposed to encapsulate. If object Fred has a class-type field that encapsulates mutable state which Fred owns (but does not encapsulate identity), a copy of the Fred should hold a reference to a copy of that object. If a field encapsulates immutable state, a copy of Fred could hold a reference to the original object or any immutable copy thereof. If it encapsulates identity, a copy of Fred must hold a reference to the original object--not a copy. If it encapsulates both identity and mutable state, then Fred cannot be copied without also copying the entire forest of inter-connected objects of which it is a part.

Related

How to perform deep copy on arrylist in java

I have a member variable
private ArrayList<CalendarableItem>[] resourceColumns = null;
and getter for the same
public ArrayList<CalendarableItem>[] getResourceColumns()
{
return resourceColumns;
}
I am seeing findbugs for above getter method.
Malicious code vulnerability : EI: Method returning array may expose internal representation
I found that I have to do a deep copy of array object to remove this error Malicious code vulnerability - May expose internal representation by incorporating reference to mutable object
I dont want to do clone of this object due to performance issue. Do we have any other better solution.
If you want the List to be immutable in depth, remove the getter. This getter returning the list give the possibility to remove, add, ... any items in it.
You could instead use something similar to an adapter to just gave the access you want. Like a specific getter or the size of the list but without giving the access to the list.
private List<CalendarableItem> resourceColumns = new ArrayList<>();
public CalendarableItem getCalendarableItem(int index){
return resourceColumns.get(index);
}
public int getSize(){ return resourceColumns.size(); }
Your list will be private an immutable (for the moment). The only access possible are those you adapt in your class.
If you want to prevent the instance to be updated, you could return a copy of it too because for the moment, the instance return is the one from the list (same reference).
EDIT : I have just notice that this was an Array of ArrayList, so this example is not quite functionnal like this, it was written for a simple ArrayList. You need to update the adapter depending on the needs.
Just a suggestion instead of using ArrayList<CalendarableItem>[] you should use List<List<CalendarableItem>>
Now coming back to your question, you can return clone of array so that in case any one make any changes to array it will not reflect in your initial array.
public ArrayList<CalendarableItem>[] getResourceColumns()
{
return Arrays.copyOf(resourceColumns, resourceColumns.length);
}
If you want/need more control then instead of method getResourceColumns() you will need to write separate methods return object at specific array index etc.

Deep copy of an object Java

I am trying to clone an object of MyGraph and I want it to be a deep copy so the arraylists inside the object are also cloned. Right now I have:
public static MyGraph deepCopy(MyGraph G){
MyGraph Copy = (MyGraph) G.clone();
Copy.VertexG = (ArrayList<Integer>) G.VertexG.clone();
Copy.EdgeG = (ArrayList<String>) G.EdgeG.clone();
return Copy;
}
This returns an error when it tries to clone the arraylist. I am not sure if this is the right way to add the arraylists to the object.
The clone operation in ArrayList returns a shallow copy of the object, and will not be suitable for your purposes. The manual workaround is to:
Create a target array list of the same size as the source list
Iterate the source list and create a clone of each of it's items, into the target list
Obviously, this will only work if the array list contains items that implement clone, and in addition that the items clone operation actually returns a deep copy. In other words, its not guaranteed. Actually, implementing deep clone functionality for Java objects is not at all easy, refer to extensive discussions in Java: recommended solution for deep cloning/copying an instance and other SO threads to get a feel for the options available. In addition to the answers provided there, here are some other options:
Serialization
If all (the required) objects in your hierarchy can be serialized then you can use this simple code to do a deep clone:
public MyGraph deepCopy() {
try {
final ByteArrayOutputStream baos = new ByteArrayOutputStream(256);
final ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
oos.close();
final ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(baos.toByteArray()));
final MyGraph clone = (QuicksortTest) ois.readObject();
return clone;
} catch (final Exception e) {
throw new RuntimeException("Cloning failed");
}
}
Note that some deep-clone libraries combine standard Java serialization with reflection hacks and/or byte code instrumentation in order to make the entire object hierarchy fully serializable. You may, or may not, need that.
Copy tools
For example, Dozer, provide fast deep-copy functionality. Orika can also achieve the same, albeit with more configuration:
public MyGraph deepCopy() {
final DozerBeanMapper mapper = new DozerBeanMapper();
final QuicksortTest clone = mapper.map(this, MyGraph.class);
return clone;
}
The only downside of course, being the additional dependencies you need to pull into your project.
On a total tangent, your deepCopy method should not be static. Also, you should seriously considering encapsulating the state of your object by making it private and implementing getters/setters.
Every class you call clone() on has to implement the Cloneable interface. From your comments, i understand your MyGraph class does not implement the Cloneable interface. In that case, Object.clone() throws the CloneNotSupportedException.
Trying to do deep copy with cloning is complicated as you need to ensure that all classes implement Cloneable interface and they have clone() definition.
Better way would be to do it through Copy Constructor or Serialization. Here is my blog on which i have discussed it in detail. hope it helps :)
A fundamental conceptual problem with cloning in Java [arguably the fundamental problem] is it's possible for a field of a type like List<String> to represent at least five very different things:
The only extant reference to a mutable list, which is used to encapsulate the mutable state thereof, but which--being the only extant reference--would not encapsulate its identity (the list could be replaced with a different list holding the same items, without altering the program's semantics). A correct clone of the object that contains this field would hold a reference to a different list holding the same items.
A reference to a mutable list which, while it would allow itself to be mutated, will never be exposed to anything that would actually mutate it. This reference may be shared with other code only if that other code will refrain from mutating the list or exposing it to code that might do so. A correct clone of the object that contains this field could hold a reference to either the original list or a different list holding the same items.
A reference to an immutable list. This reference may be shared freely with other code without regard for how that code might expose it. As above, the correct clone of the object containing this field could hold a reference to either the original list or a copy.
A reference to a mutable list which is owned by some other object, which is held for purpose of binding this to those aspects of the other object's state which are encapsulated in the list. A correct clone of the object holding the field must hold a reference to that same list, and not a copy thereof.
A reference to a mutable list which this object owns, but to which other objects also have a reference for purpose of either observing this object's state, or feeding information to this object. The object holding this field cannot be correctly cloned in isolation, though it might be possible to clone a group of inter-connected objects and give the new set of objects a set of interconnections which was isomorphic to those in the original group.
The concrete type of the object to which the field holds a reference may distinguish between some of the above cases, but it cannot distinguish among all of them. In particular, the first and fourth scenarios require different behavior on the part of the cloning method, despite the fact that in both scenarios the reference might likely pointing to an ArrayList<string>.

Is it possible to change a variables value from an array

This is a little confusing question for me to express, but I'll do my best.
So:
ArrayList<Object> fieldList = new ArrayList<Object>();
I then dump a lot of different variables to this array:
fieldList.add(objectsURL); //string
fieldList.add(X); //int
fieldList.add(Y); //int
...
If I change the variable, the values in the array change
too-confirming the array stores a reference to the memory, rather
then value itself.
However, if I then retrieve data from the array then set that...
Object object = ((String)this.fieldList.get(0));
Then set object
object = "meeep!"
objectsURL is not set to "meep!" but rather it retains its original
value.
I assume this is because the "object" is not referencing the original
variable anymore, that instead its pointing to a new immutable string
in the memory.
All expected Java behavior I think....but then, how would I go about
setting the actual original variable? is this possible in java?.
So, in other words. Given only access to "fieldList" is it possible to change the value of
"objectsURL"?
So, if:
String objectsURL = "www.google.com"
fieldList.add(objectsURL);
Is there a way to set objectsURL to "www.stackoverflow.com" using only a reference from fieldList?
I dont want to change the fact that fieldList contains "objectsURL", I want to change what string the variable "objectsURL" actualy contains.
If not, is there an alternative method to achieve the same thing?
I hope my question explains the problem well enough.
My use-case is trying to make a serialization/
deserialization system for a bunch of my objects. I was hoping to put
all the fields into a arraylist I could retrieve for both reading and
writing....thus avoiding having to hard-code long lists of
field[0]=blah and blah=field[0] and then going though constant pains
of needing to renumber them each time I add a new field before
another.
(I cant use Javas inbuilt serialization, as I am using GWT and this is client side only.)
Thanks,
I assume this is because the "object" is not referencing the original variable anymore, that instead its pointing to a new immutable string in the memory.
Correct, each time you use the assignment operator = on an object you change the object it refers to, not the object itself.
To change the values in the List, you use the .set method of an ArrayList
this.fieldList.set(0, newValue);
Since your variable is a String, there is no way you can change the String-variable through the list
Your alternatives:
using a char-array
List myList = new ArrayList();
char[] charArray = "My String".toCharArray();
myList.add(charArray);
charArray[0] = 'A';
String theString = new String(myList.get(0)); // "Ay String"
If you use a char-array, make sure that the length of the array is enough to contain the number of characters you want to have in the future, because to change the length of the array you will need to create a new array (array lists can be expanded dynamically, arrays can not)
Embed the String inside your own class (I have ignored getters and setters here)
class MyString {
public String value;
public MyString(String value) {
this.value = value;
}
}
MyString myStr = new MyString("some value");
list.add(myStr);
((MyString) list.get(0)).value = "a new value";
System.out.println(myStr.value); // will print "a new value"
Strings are immutable, so it is impossible to change the contents of a String object. Also, you cannot use the list to change what object the reference variable objectsURL points to. To achieve what you want, you will need to create a custom class that has a String member. You can then store instances of this class in a List and change the String references to via the references in the list. The changes will then be reflected in any other reference variables which refer to the objects in the list.
First, you declare a variable 'object' and assign some Object out of the ArrayList. Later you assign some other object "meeep!" to this variable. There is no reason that your 'object' variable is related to the ArrayList.

Deep copy of an object array

I want to make a deep copy of an object array using a constructor.
public class PositionList {
private Position[] data = new Position[0];
public PositionList(PositionList other, boolean deepCopy) {
if (deepCopy){
size=other.getSize();
data=new Position[other.data.length];
for (int i=0;i<data.length;i++){
data[i]=other.data[i];
}
However, what I have above for some reason is not working. I have automated tests that I run, and its failing those tests. So theres an error an here that Im not sure what it is.
What you have implemented is a shallow copy. To implement a deep copy, you must
change
data[i] = other.data[i];
to some thing that assigns a copy of other.data[i] to data[i]. How you do this depends on the Position class. Possible alternatives are:
a copy constructor:
data[i] = new Position(other.data[i]);
a factory method:
data[i] = createPosition(other.data[i]);
clone:
data[i] = (Position) other.data[i].clone();
Notes:
The above assume that the copy constructor, factory method and clone method respectively implement the "right" kind of copying, depending on the Position class; see below.
The clone approach will only work if Position explicitly supports it, and this is generally regarded as an inferior solution. Besides, you need to be aware that the native implementation of clone (i.e. the Object.clone() method) does a shallow copy1.
In fact the general problem of implementing deep copying in Java is complicated. In the case of the Position class, one would assume that the attributes are all primitive types (e.g. ints or doubles), and therefore a deep versus shallow copying is moot. But if there are reference attributes, then you have to rely on the copy constructor / factory method / clone method to do the kind of copying that you require. In each case it needs to be programmed in. And in the general case (where you have to deal with cycles) it is difficult and requires each class to implement special methods.
There is one other potential way to copy an array of objects. If the objects in the array are serializable, then you can copy them by using ObjectOutputStream and ObjectInputStream serialize and then deserialize the array. However:
this is expensive,
it only works if the objects are (transitively) serializable, and
the values of any transient fields won't be copied.
Copying by serialization is not recommended. It would be better to support cloning or some other method.
All in all, deep copying is best avoided in Java.
Finally, to answer your question about the Position classes copy constructor works, I expect it is something like this:
public class Position {
private int x;
private int y;
...
public Position(Position other) {
this.x = other.x;
this.y = other.y;
}
...
}
As #Turtle says, there's no magic involved. You implement a constructor (by hand) that initializes its state by copying from an existing instance.
1 - It is specified that the Object implementation of clone() does a shallow copy, but this may be overridden. The javadoc for clone specifies the "contract" as follows:
"Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object. The general intent is that, for any object x, the expression: x.clone() != x will be true, and that the expression: x.clone().getClass() == x.getClass() will be true, but these are not absolute requirements. While it is typically the case that: x.clone().equals(x) will be true, this is not an absolute requirement."
Nothing in the "contract" talks about deep versus shallow copying. So if you are going to use clone in this context, you need to know how the actual classes clone method behaves.
When you say:
data[i]=other.data[i];
You are just copying a list of references (assuming this is an array of objects). If you want to make a deep copy, you need to use new to create a new instance of each object in the array.
Instead of saying:
data[i]=other.data[i]
You will want to make a copy constructor for Position (in other words, a constructor for Position that takes in another Position and copies the primitive data inside it) and say data[i]=new Position(other.data[i]);
Basically your "deep copy" constructor the PositionList is a copy constructor, although copy constructor does tend to indicate a deep copy, so the deepCopy parameter is unnecessary.
Here is a function I use:
function copy(arr) {
return arr
.map(x => Object
.keys(x)
.reduce((acc, y) => {
acc[y] = x[y]
return acc
}, {}))
}
It only works on arrays with objects with a single level.
This should make a "deep" copy
int [] numbers = { 2, 3, 4, 5};
int [] numbersClone = (int[])numbers.clone();

How to make a separated copy of an ArrayList? [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Java: how to clone ArrayList but also clone its items?
I have a sample program like the following:
ArrayList<Invoice> orginalInvoice = new ArrayList<Invoice>();
//add some items into it here
ArrayList<Invoice> copiedInvoice = new ArrayList<Invoice>();
copiedInvoice.addAll(orginalInvoice);
I thought I can modify items inside the copiedInvoice and it will not affect these items inside originalInoice. But I was wrong.
How can I make a separated copy / clone of an ArrayList?
Thanks
Yes that's correct - You need to implement clone() (or another suitable mechanism for copying your object, as clone() is considered "broken" by many programmers). Your clone() method should perform a deep copy of all mutable fields within your object. That way, modifications to the cloned object will not affect the original.
In your example code you're creating a second ArrayList and populating it with references to the same objects, which is why changes to the object are visible from both Lists. With the clone approach your code would look like:
List<Foo> originalList = ...;
// Create new List with same capacity as original (for efficiency).
List<Foo> copy = new ArrayList<Foo>(originalList.size());
for (Foo foo: originalList) {
copy.add((Foo)foo.clone());
}
EDIT: To clarify, the above code is performing a deep copy of the original List whereby the new List contains references to copies of the original objects. This contrasts to calling ArrayList.clone(), which performs a shallow copy of the List. In this context a shallow copy creates a new List instance but containing references to the original objects.
If you are storing mutable objects into the ArrayList, you will need to copy each object when you copy the ArrayList. Otherwise, the new ArrayList will still hold the original references.
However if you're storing immutable objects, it's fine to use:
ArrayList copiedInvoice = new ArrayList(originalInvoice);
I thought I can modify items inside the copiedInvoice and it will not affect these itmes inside originalInoice.
This happens because what gets copied is the reference variable and not the object it self.
Hence you end up with two "references" pointing to the same object.
If you need to copy the whole object you may need to clone it.
But you might have problems if you don't clone the object internal attributes if they happen to be other objects.
For instance the following class definition won't give you any problem.
public class Something {
private int x;
private int y;
private String stringObject;
}
If you create a copy of that, you would copy the current values of its attributes and that's it.
But if your class do have another object inside you might consider to clone it too.
class OtherSomething {
Something something;
private int x;
}
If you do the following:
Something shared = new Something();
OtherSomething one = new OtherSomething();
OtherSomething two = new OtherSomething();
one.something = shared;
two.something = shared;
In this case, both one and two have the same reference variable to the same shared "something" and changing the value in one would affect the other.
That's why it is much simpler/better/easier to use immutable objects.
If you need to change the value of an immutable object you just create a new one with the correct value.
Take a look at ByteArrayOutputStream and ByteArrayInputStream. If all of your classes implement Serializable, then you can make a copy using the above mentioned classes.

Categories