Java function parameter value is being changed - java

I've written a function which. Problem is, the parameters I'm sending, is being manipulated in the main program, though it is not my intention. I just want to have the value inside the function, but while operating, the actual value in the main program is also being changed.
How can I prevent this?
Here is my code:
Tiles[][] MoveRight(Tiles[][] tilesArray) {
Tiles[][] tempTilesArray = new Tiles[3][3];
Tiles[][] tempTilesArrayToSend = new Tiles[3][3];
tempTilesArrayToSend = CopyTilesArrays(tilesArray, tempTilesArrayToSend);
ArrayIndex zeroPos = FindZero(tilesArray);
Tiles zeroTile = GetTile(zeroPos, tilesArray);
if (zeroPos.column != 2) {
ArrayIndex otherPos = new ArrayIndex(zeroPos.row,
zeroPos.column + 1);
tempTilesArray = SwapTilesPositions(zeroTile, GetTile(otherPos,
tilesArray), tempTilesArrayToSend);
}
return tempTilesArray;
}
The array I'm sending inside the SwapPositionFunction is actually modifying the tilesArray itself. Though I've made a new instance of tiles array and then sent it.

Without seeing what is done in
CopyTilesArrays (tilesArray, tempTilesArrayToSend);
we can not say much.
Note, that in Java, there is no pass-by-value or pass-by-reference, but a copy of the reference is passed to the methods. This copy of a reference will - in case of objects and Arrays - point to the same, original object, so if you change the underlying/embedded object, the original object is affected, but if you change the reference, the original object is not affected.
IF you want to pass an independent copy of your array, you have to perform a deep ocpy. Maybe that is, what CopyTilesArrays is supposed to do, but without seeing it, we don't know.
Note too, that there are, or better: that there can be several layers of objects, with different reasons to stay on the surface, to go to the core, or to stay somewhere in between.
For example, to make a deep copy from the Array of Array of Tiles, you could do something like this:
public class TilesCopy {
Tiles[][] copyTilesArrays (Tiles[][] from, int outer, int inner) {
Tiles[][] to = new Tiles[outer][inner];
int o = 0;
for (Tiles [] tiles: from) {
Tiles[] fresh = new Tiles [inner];
int i = 0;
for (Tiles t : tiles)
{
fresh[i] = t.deepCopy ();
i++;
}
to [o] = fresh;
o++;
}
return to;
}
}
Note, that in the innermost loop, the elements aren't just referenced with fresh[i] = t;, but with a deep copy, to keep the objects in the original Array unaffected.
You could copy an array of arrays of Tiles in multiple other ways. For example, you could rearrange the outer array. If the Tiles were
[[A][B][C]]
[[D][E][F]]
[[G][H][I]]
you could copy them, and modify the target to be:
[[G][H][I]]
[[D][E][F]]
[[A][B][C]]
with just copying the outer arrays, and rearranging them. And you could copy the inner arrays, to be:
[[C][B][A]]
[[F][E][D]]
[[I][H][G]]
If you now modify the A to a, the original A will be affected too, without a deep copy:
[[C][B][a]]
[[F][E][D]]
[[I][H][G]]
[[a][B][C]]
[[D][E][F]]
[[G][H][I]]

Related

How do I make a copy of an Array, which I can return in a public method?

Basically I got told that I shouldn't have public methods returning Arrays for "future" security purposes. Instead they should be private, and if I wanna return an Array it would have to be some kind of copy in another method.
This is how it looks now..
public Object[] ownedObject() {
return objectArr;
}
If I make this private the class that needs it doesn't recognize the method above.
Thing is I need to use the contents in that Array in said, other class, and the total project, as I have it right now with 5 different classes, works (with the returning Array-methods set to Public and not private).
As you are concerned with security aspect of this problem you might want to distinguish between shallow copy and deep copy of the array. If your array contains mutable objects you probably need a deep copy of every single element in the array to ensure that state is not leaking from your object.
Assuming that you array is of type MyType with a copy constructor:
public MyType[] ownedObject() {
MyType[] copyArr = new MyType[objectArr.lenght];
for (int i = 0; i < objectArr.lenght; i++) {
copyArr[i] = new MyType(objectArr[i]);
}
return copyArr;
}
There are also other ways to deep copy an object.

How is a Java ArrayList modified when passed as parameter to function that returns void and modified in function? May be confused on pass-by-value

I have a block of Java code that modifies an ArrayList by passing the ArrayList into a method, modifying the list in the method, and returns void. I thought that Java's pass-by-value would cause the original ArrayList to not be modified. What am I misunderstanding?
public class Question {
public static void weaveLists(LinkedList<Integer> first, LinkedList<Integer> second, ArrayList<LinkedList<Integer>> results, LinkedList<Integer> prefix) {
/* One list is empty. Add the remainder to [a cloned] prefix and
* store result. */
if (first.size() == 0 || second.size() == 0) {
LinkedList<Integer> result = (LinkedList<Integer>) prefix.clone();
result.addAll(first);
result.addAll(second);
results.add(result);
return;
}
/* Recurse with head of first added to the prefix. Removing the
* head will damage first, so we’ll need to put it back where we
* found it afterwards. */
int headFirst = first.removeFirst();
prefix.addLast(headFirst);
weaveLists(first, second, results, prefix);
prefix.removeLast();
first.addFirst(headFirst);
/* Do the same thing with second, damaging and then restoring
* the list.*/
int headSecond = second.removeFirst();
prefix.addLast(headSecond);
weaveLists(first, second, results, prefix);
prefix.removeLast();
second.addFirst(headSecond);
}
public static ArrayList<LinkedList<Integer>> allSequences(TreeNode node) {
ArrayList<LinkedList<Integer>> result = new ArrayList<LinkedList<Integer>>();
if (node == null) {
result.add(new LinkedList<Integer>());
return result;
}
LinkedList<Integer> prefix = new LinkedList<Integer>();
prefix.add(node.data);
/* Recurse on left and right subtrees. */
ArrayList<LinkedList<Integer>> leftSeq = allSequences(node.left);
ArrayList<LinkedList<Integer>> rightSeq = allSequences(node.right);
/* Weave together each list from the left and right sides. */
for (LinkedList<Integer> left : leftSeq) {
for (LinkedList<Integer> right : rightSeq) {
//This is the part I don't understand
ArrayList<LinkedList<Integer>> weaved = new ArrayList<LinkedList<Integer>>();
weaveLists(left, right, weaved, prefix);
result.addAll(weaved);
}
}
return result;
}
}
I would expect that the weaved array would not be modified when the result.addAll(weaved) is called, but weaved array is modified after the call to weaveLists(), even though it returns void.
You create a weaved reference to an ArrayList object that stored in memory. When you call new operator then a new object allocated in the memory. Then you pass the reference weaved to the weaveLists() method.
This method have a reference result, but this is only a reference that refer to the same object in the memory, because only new operator allocate a new memory. So, the weaveLists() method modify your original ArrayList. It is a major feature that you should understand, I suggest you to read the difference between pass-by-value and pass-by-reference.
To answer the question in short - you are misunderstanding what does the pass-by-value mean in Java.
If you pass an object (list in this case) and manipulate it's elements without changing it's reference, it is the same object you passed, nothing changed on the object (list) itself, it has the same reference it had when passed to function, but changes do apply to any of the elements being manipulated.
Pass by value in this context only means that if you created a new instance of a given list within the function and then manipulated it - no changes would apply on original list, since that would be observed as a local variable, not the passed one.
Check top answers to this question, or just read some java basics related to pass-by-value. Use this blog, or any other that you might like more.

Memory usage/ reference in java

I am going to ask a basic question about Java memory usage.
Imagine we have an array List and it is large enough and we don't like to use more memory. Now if I want to pass this array to another methods in this class, or other classes through their constructor or method, do I need additional memory/is there additional memory usage for this array?
If yes, could I just make this array package level, and therefore the other classes in this package could access it directly, without any memory need.
Thank you in advance.
No, no additional memory is necessary. The parameter of a function is passed by copy of the reference. It means that for any kind of object only 4 additional bytes are used.
If you pass an array as parameter and you modify it in the body of the method the changes will be exported outside of method.
Instead if you reassign the array variable, the difference is not visible externally.
This happens because the parameters are passed as copy of the reference and not by reference.
public void vsibleModification(int[] a) {
for (int i = 0; i < a.length; i++) {
// This change is visible outside of method because I change
// the content of a, not the reference
a[i] = a[i] + 1;
}
}
public void nonVisibleModification(int[] a) {
// Non visible modification because a is reassigned to a new value (reference modification)
a = new int[2];
a[0] = 1;
a[1] = 2;
}

Deep copy of 2D array with all elements

I am making a basic game using a 2D array (4x4) in which the elements (of object type with ints 1 to 16) must be switched around to reach a particular goal state, this state must be compared with the current state, hence the need for copying.
So far I have:
public void cloneArray() throws CloneNotSupportedException
{
ClassName copy = (ClassName)super.clone();
copy.tiles = (Tile[][]) tiles.clone();
}
Does this appear to be right, or am I missing something out?
You'll need to go one step further and do like so :
ClassName copy = (ClassName)super.clone();
copy.tiles = (Tile[][]) tiles.clone();
for(int i = 0; i < copy.tiles.length; i++) {
copy.tiles[i] = (Tile[]) tiles[i].clone();
}
The reason is that clone makes a shallow copy of the top-level array, which is holding references to other arrays.

Simulating pass by reference for an array reference (i.e. a reference to a reference) in Java

I was wondering, in java, is it possible to in anyway, simulate pass by reference for an array? Yes, I know the language doesn't support it, but is there anyway I can do it. Say, for example, I want to create a method that reverses the order of all the elements in an array. (I know that this code snippet isn't the best example, as there is a better algorithms to do this, but this is a good example of the type of thing I want to do for more complex problems).
Currently, I need to make a class like this:
public static void reverse(Object[] arr) {
Object[] tmpArr = new Object[arr.length];
count = arr.length - 1;
for(Object i : arr)
tmpArr[count--] = i;
// I would like to do arr = tmpArr, but that will only make the shallow
// reference tmpArr, I would like to actually change the pointer they passed in
// Not just the values in the array, so I have to do this:
for(Object i : tmpArr)
arr[count++] = i;
return;
}
Yes, I know that I could just swap the values until I get to the middle, and it would be much more efficient, but for other, more complex purposes, is there anyway that I can manipulate the actual pointer?
Again, thank you.
is there anyway that I can manipulate the actual pointer?
Java does not pass by reference, so you can't directly manipulate the original pointer. As you've found out, Java passes everything by value. You can't pass a reference to an array object, and expect a method to modify the original reference to point to another array object.
You can, of course:
Modify elements of the referred array object (ala java.util.Arrays.sort)
Pass a reference to an object with a settable field (e.g. Throwable has a setStackTrace)
return the new reference instead (ala java.util.Arrays.copyOf)
Well, you can explicitly pass an object that contains a reference. java.util.concurrent.atomic.AtomicReference is ready out of the box, although it does come with volatile semantics that you probably don't want. Some people use single element arrays to returns values from anonymous inner classes (although that doesn't seem a great idea to me).
This method reverses the Array's elements in place. The caller sees the changes. (In Java everything is passed by value, including object references.)
public static void reverse(Object[] arr) {
for ( int i = 0, j = arr.length - 1; i < j; i++, j-- ) {
Object temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
In Java Object reference is passed by value.
So if you looking for something like
function referenceCheck()
{
int[] array = new int[]{10, 20, 30};
reassignArray(&array);
//Now array should contain 1,2,3,4,5
}
function reassignArray(int **array)
{
int *array = new int[] { 1, 2, 3, 4, 5};
}
Then its not possible in Java by any direct means.
If we need to change only the values stored in an array, then we can do it since object reference is passed by value.
You want to pass a reference to the array reference. In that case you just have to either create a class to hold the reference and pass a reference to that class or just pass a 1-element array of the type being passed. Then you'd be passing either an object holding the array or an array whose only element contains the array you want to operate on.

Categories

Resources