This question about a 2D array being passed into a method came up in class. Can someone explain why the original array d is unchanged after a call to doStuff() ? I debugged the code and saw that the method was reversing the values, but then when returned, the original array remained unchanged. I thought passing arrays into a method and changing values in that method would affect the original array. Here that is not the case, the original array is unchanged. My first thought was the orignal would be reversed. But no.
Initialize the array d and call doStuff as
follows:
int d[][] = { {-1,0,1},
{5,6,7},
{2,3,4} };
doStuff(d);
public static void doStuff (int [][] frst)
{
int len = frst.length;
int sec[][] = new int[len] [];
for (int j=0; j<len; j++)
{
sec[j] = frst[len –j -1];
}
frst = sec;
}
You already have some good answers, but here's a bit of code showing the two cases that may seem to be inconsistent, but are indeed explained by the fact that java is pass-by-value. The tricky bit is that in the case of arrays, it's the reference to the array that's being passed by value, not the array itself.
Hence the called function receives a copy of the reference to the same array as the caller function, and can modify elements within that array. But when the called function modifies the reference itself to refer to a different array it is modifying a copy, which has no effect on the caller --- that is, in the caller environment the variable is still referring to the original array.
This is easier to explain with boxes and arrows :-), but hopefully the code and output below will be helpful:
$ cat PBV.java
class PBV
{
private static void modfiyArrayElement(int[] intArray) {
// intArray is referring to the same array as in main
intArray[0] = 17;
}
public static void main(String[] args) {
int[] a = new int[]{ 1, 2, 3 };
System.out.println(a[0]);
modifyArrayElement(a);
System.out.println(a[0]);
}
}
$ java PBV
1
17
$ cat PBV2.java
class PBV2
{
private static void modfiyArrayReference(int[] intArray) {
System.out.println("\nIn modifyArrayReference:");
System.out.println("intArray[0] is " + intArray[0]);
System.out.println("ref value of intArray is: " + intArray);
intArray = new int[] { 100, 200, 300 };
// intArray is no longer referring to the same array as in main!
// at this point munging with intArray won't have an effect in main
System.out.println("\nintArray[0] is now " + intArray[0]);
System.out.println("ref value of intArray is: " + intArray +"\n");
}
public static void main(String[] args) {
System.out.println("in main:");
int[] a = new int[]{ 1, 2, 3 };
System.out.println("a[0] is " + a[0]);
System.out.println("ref value of a is: " + a);
modfiyArrayReference(a);
System.out.println("back in main:");
System.out.println("a[0] is still " + a[0]);
System.out.println("ref value of a is still: " + a);
}
}
$ java PBV2
in main:
a[0] is 1
ref value of a is: [I#55a6c368
In modifyArrayReference:
intArray[0] is 1
ref value of intArray is: [I#55a6c368
intArray[0] is now 100
ref value of intArray is: [I#37670cc6
back in main:
a[0] is still 1
ref value of a is still: [I#55a6c368
Java is pass by value
Return your value and set it to your value.
int d[][] = { {-1,0,1},
{5,6,7},
{2,3,4} };
d = doStuff(d);
public static int[][] doStuff (int [][] frst)
{
int len = frst.length;
int sec[][] = new int[len] [];
for(int j=0; j<len; j++)
sec[j] = frst[len-j-1];
return sec;
}
}
You can also set the value of the passed array directly (array variables are a reference to an array, so editing the elements of your passed array reference will work:
public static void doStuff (int [][] frst)
{
int len = frst.length;
int sec[][] = new int[len] [];
for(int j=0; j<len; j++)
sec[j] = frst[len-j-1];
for(int j=0; j<frst.length;j++)
frst[j] = sec[j]
}
Here what happens.
There are 2 arrays created, the initial one and the second, created inside the doStuff method.
There are 3 references (variables) to the arrays in the code:
external (for the method): d
internal: first and sec.
Inside the doStuff method the second array is indeed populated as the reverse of the initial which is not changed at all.
At the end of the doStuff method both first and sec reference the same object, the second one, and not the original - hence the behavior you see
Related
import java.util.ArrayList;
public class Paaohjelma {
public static int pienin(int[] taulukko) {
int temp, size;
size = taulukko.length;
for(int i = 0; i<size; i++ ){
for(int j = i+1; j<size; j++){
if(taulukko[i]>taulukko[j]){
temp = taulukko[i];
taulukko[i] = taulukko[j];
taulukko[j] = temp;
}
}
}
return taulukko[0];
}
public static int pienimmanIndeksi(int[] taulukko) {
ArrayList<Integer> tauli = new ArrayList<>();
for (int i : taulukko) {
tauli.add(i);
}
return tauli.indexOf(Paaohjelma.pienin(taulukko));
}
public static int pienimmanIndeksiAlkaen(int[] taulukko, int aloitusIndeksi) {
// this methods should get the index of smallest value starting from specified index
int[] tempTauli = taulukko;
tempTauli = new int[tempTauli.length - aloitusIndeksi];
// this gets the right values to temporary array
if (aloitusIndeksi > 0) {
int index = 0;
int indexTauli = 0;
for(int value : taulukko) {
if(index >= aloitusIndeksi) {
tempTauli[indexTauli] = taulukko[index];
indexTauli++;
}
index++;
}
}
// values added are automatically sorted from smallest to largest?
// this shouldn't be, array should be 5, 99, 3, 12 but is shown as 3, 5, 12, 99
for(int inty : tempTauli) {
System.out.println(inty);
}
// get the index of smallest value in array
// index is 0 should be 2
int index = Paaohjelma.pienimmanIndeksi(tempTauli);
// return index of smallest value (add starting index to get the index of smallest value in the original array when starting from specified index)
return index+aloitusIndeksi;
}
public static void main(String[] args) {
// test code
int[] taulukko = {3, 1, 5, 99, 3, 12};
int minIndex = Paaohjelma.pienimmanIndeksi(taulukko);
System.out.println("Pienin: " + Paaohjelma.pienin(taulukko));
System.out.println("Pienimmän indeksi: " + minIndex);
System.out.println(Paaohjelma.pienimmanIndeksiAlkaen(taulukko, 2));
}
}
Hello! I'm doing some programming course work for school and have been stuck in this particular part for couple hours. So I decided it would be best for someone else to take a look and provide some light why my approach for this problem isn't working.
What should happen: class method PienimmanIndeksiAlkaen should return the index of smallest value in provided int array starting from specified index.
The main problem I have been having is that the array seems to be automatically sorting itself and I have no idea what is possible causing this. I have commented the relevant part of the code and would be more than happy if someone could explain why this is happening and what possible could be done to prevent this.
The reason your array is sorted is when you call
System.out.println("Pienin: " + Paaohjelma.pienin(taulukko));
you sort the array.
When you pass the array into this function, you aren't actually passing the value of the array, but the pointer to the array - the address of the array in memory. This is the difference between passing parameters by value or by reference.
How do you know if the value is passed by value or by reference?
As a rule of thumb:
primitive values - i.e. int, double, etc. will be passed by value - their value will be copied and passed to the function.
Any other type, namely arrays and classes, will be passed by reference - the address of the value in memory will be passed to the function, thus any change to the value inside the function will affect it when the function ends too.
Read more here
This question already has answers here:
Are arrays in java pass by reference or pass by value?
(3 answers)
Closed 2 years ago.
I am trying to merge to arrays nums1 and nums2...
m = size of filled elements in nums1
n = size of nums2
An array is passed by reference in a method...So if any change occur inside a method, it will reflect outside it...So then I assign nums1 = result inside merge method...it's showing inside the the merge method, when I print the nums1 array by below code:
System.out.println("Result: " + Arrays.toString(nums1));
..So the nums1 array will now point towards "result" array..
but when I try to print the same inside the "main" method by the code below:
System.out.println("Merged Array: " + Arrays.toString(nums1));
Then it's not showing the desired result.i.e nums1 should show the "result array values" as change din the "merge" method..
Please someone explain why this is happening?
My entire code of merging the two arrays is as below:
public class MergeSortedArray {
public static void main(String[] args) {
int[] nums1 = {1, 2, 3, 0, 0, 0}, nums2 = {2, 5, 6};
int m = 3, n = 3;
System.out.println("Original Array: nums1: " + Arrays.toString(nums1));
System.out.println("Original Array: nums2: " + Arrays.toString(nums2) + "\n");
merge(nums1, m, nums2, n);
System.out.println("Merged Array: " + Arrays.toString(nums1));
}
public static void merge(int[] nums1, int m, int[] nums2, int n) {
int n1idx = 0, n2idx = 0;
int[] result = new int[nums1.length];
int ridx = 0;
while(n1idx < m && n2idx < n) {
if(nums1[n1idx] < nums2[n2idx]) {
result[ridx++] = nums1[n1idx++];
} else {
result[ridx++] = nums2[n2idx++];
}
}
// fill the remaining elements from nums1
while(n1idx < m) {
result[ridx++] = nums1[n1idx++];
}
// fill the remaining elements from nums2
while(n2idx < n) {
result[ridx++]= nums2[n2idx++];
}
nums1 = result;
System.out.println("Result: " + Arrays.toString(nums1));
}
}
When you assign result to nums1, it does not change the reference in the called program. It is of local significance only. This is because the actual reference is passed by value and you can't change that with a simple assignment.
However, any changes you make to nums1 contents in the merge method will be reflected in the calling program since you are changing what the reference refers too and not the reference itself.
Everything in Java is passed by value. Even arrays and objects.
Here is an example. The Identityhash shows a value indicative of the reference. Note that after the last assignment in the method, the passed reference was not changed.
public static void main(String[] args) {
int[] q = {4,5,6};
System.out.println("q in main = " + System.identityHashCode(q));
callMethod(q);
System.out.println("q in main = " + System.identityHashCode(q)); // hasn't changed
}
public static void callMethod(int[] v) {
System.out.println("v in method = " + System.identityHashCode(v));
int[] otherArray = new int[]{1,2,3};
v = otherArray;
System.out.println("v in method after assignment = " + System.identityHashCode(v));
}
Prints
q in main = 925858445
v in method = 925858445
v in method after assignment = 798154996
q in main = 925858445
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 4 years ago.
public class Test {
public static void main(String[] args) {
int[] oldList = {1, 2, 3, 4, 5};
reverse(oldList);
for (int i = 0; i < oldList.length; i++)
System.out.print(oldList[i] + " ");
}
public static void reverse(int[] list) {
int[] newList = new int[list.length];
for (int i = 0; i < list.length; i++)
newList[i] = list[list.length - 1 - i];
list = newList;
}
}
how come the method does not apply and still get 1 2 3 4 5?
thank you !
This is happening because Java is pass by value. This means that when you pass an argument into a method you are passing the reference to it, not the argument itself. The changes that you make inside the method are resolved but in this case you don't return the modified argument. Try this simple experiment to see what I mean:
public static void main(String[] args) {
int x = 0;
foo(x);
System.out.println(x);
}
public static void foo(int x) {
x = 4;
}
This program will print 0 because the changes are essentially discarded. To return the copied reference try this:
public static int[] reverse(int[] list) {
int[] newList = new int[list.length];
for (int i = 0; i < list.length; i++) {
newList[i] = list[list.length - 1 - i];
}
return newList;
}
And in your main:
oldList = reverse(oldList);
A much more in depth answer:
Is Java "pass-by-reference" or "pass-by-value"?
There are couple of issues. You can fix it with below two Options:
Option 1:
1) Make a new copy of original array and use it as reference array to reverse
2) In reverse function, update values of array that has been passed in parameter and reverse it using reference array
public class Test {
public static void main(String[] args) {
int[] oldList = {1, 2, 3, 4, 5};
reverse(oldList);
for (int i = 0; i < oldList.length; i++)
System.out.print(oldList[i] + " ");
}
public static void reverse(int[] list) {
// create a copy of initial array to use it to reverse
int[] newList = Arrays.copyOf(list,list.length);
for (int i = 0; i < list.length; i++)
// update original array and reverse it. Calling method still have reference to this array
list[i] = newList[list.length - 1 - i];
}
}
Console Output:
PS: Here the idea is to ensure the reference of array remains the same. You can do it using another array as reference array or using another local variable and swapping two values inside array or doing XOR between i and n-i-1 variable. There are n number of ways out of which 1 has been shared above.
Option 2:
1) No need to copy the reference of the old array to new array in reverse method
2) Return the new array reference back to the calling method
3) For above point you will also have to change the return type of reverse function
4) Save the new reference of array in a variable in the main method and then print from the same.
Please find my comments below:
public class Test {
public static void main(String[] args) {
int[] oldList = {1, 2, 3, 4, 5};
//save the return list to a variable
int[] newList= reverse(oldList);
for (int i = 0; i < newList.length; i++)
//print the data from new list
System.out.print(newList[i] + " ");
}
// change the return type
public static int[] reverse(int[] list) {
int[] newList = new int[list.length];
for (int i = 0; i < list.length; i++)
newList[i] = list[list.length - 1 - i];
//remove this line as there is no point of copying old array back to new array
// list = newList;
//retrun newlist reference to the calling method
return newList;
}
}
Console Output:
This is happening because you are altering the new area, and the statement list = newList; does not affect the original list because java is pass by value and you only overwrite the pointer in the reverse function.
Instead you should return the new array and overwrite the old one like:
public class HelloWorld
{
public static void main(String[] args) {
int[] oldList = {1, 2, 3, 4, 5};
oldList = reverse(oldList);
for (int i = 0; i < oldList.length; i++)
System.out.print(oldList[i] + " ");
}
public static int[] reverse(int[] list) {
int[] newList = new int[list.length];
for (int i = 0; i < list.length; i++)
newList[i] = list[list.length - 1 - i];
return newList;
}
}
Java is always pass-by-value. What does this mean for object- and array-references? In Java, we handle objects only through references. References live on the stack, the actual objects live on the heap. References store the address where the actual object resides.
If you pass an object to a method, the reference-value (i.e. the address where the object resides) is passed as parameter. For some method foo(Object o) this means: if you re-assign o in foo's body (e.g. through o = new Object();, this change will not be visible outside the method.
To fix you problem, you would either have to do the reversal in-place (i.e. on list directly) or return your newly created array. Here is an implementation of the in-place variant:
public static void reverse(final int[] values) {
final int length = values.length;
for (int i = 0; i < length / 2; ++i) {
final int j = length - i - 1;
swap(values, i, j);
}
}
public static void swap(final int[] values, final int i, final int j) {
int tmp = values[i];
values[i] = values[j];
values[j] = tmp;
}
For an implementation of the return-variant, look at one of the other answers since every other answer seems to implement a variant on this.
Some remarks on your code:
Giving an array-parameter the name list is confusing. A list is not the same as an array, the are different datastructures with differen properties.
You should never neglect the optional parentheses around one-line if-, else-, for-,... bodies. This can be the source of nasty bugs and is regarded as bad practice.
You should take a little bit more care wrt. your indentation. Keep in mind that your source code is a means of coummuncation. The more semantics you can transport through simple rules (like indentation), the easier it is to understand your source code.
There is an example program in my java book that makes no sense to me. Basically it passes an array reference to a method. But the outcome is that the array itself is modified even though the method doesn't have a return or something within it that indicates its doing something other than creating it's own instance of the array.
public class PassArray
{
public static void main( String[] args )
{
int[] array = { 1, 2, 3, 4, 5 };
System.out.println(
"Effects of passing reference to entire array:\n" +
"The values of the original array are:" );
for ( int value : array )
System.out.printf( " %d", value );
modifyArray( array ); // pass array reference to method modifyArray
System.out.println( "\n\nThe values of the modified array are:" );
// output the value of array (why did it change?)
for ( int value : array )
System.out.printf( " %d", value );
} // end main
// multiply each element of an array by 2
public static void modifyArray( int array2[] ) // so this accepts an integer array as an arguement and assigns it to local array array[2]
{
for ( int counter = 0; counter < array2.length; counter++ )
array2[ counter ] *= 2;
} // What hapened here? We just made changes to array2[] but somehow those changes got applied to array[]??? how did that happen?
//What if I wanted to not make any changes to array, how would implement this code so that the output to screen would be the same but the value in array would not change?
} // end class PassArray
Please explain why this is the case and also how this could be implemented somehow so that the values of array are not changed. S
// What hapened here? We just made changes to array2[] but somehow those changes got applied to array[]??? how did that happen?
Because java is pass by reference value. Copy of the reference will be passed to the method. This reference also still points to original array. Any change you perform on this reference will reflect on original array.
how this could be implemented somehow so that the values of array are not changed.
One way is, create new array inside the method and assign it this reference.
Example:
public static void modifyArray( int array2[] )
{
array2 = new int[10];
//Copy only ten elements from outer array, which populates element at index 2.
for ( int counter = 0; counter < array2.length; counter++ )
array2[ counter ] *= 2;
}
Now the updates/operations you perform on this reference will effect on new array created inside the method, not on original array.
See this SO discussion for more information.
When you pass an array to a method, you're really just passing a copy of the reference to the array.
Any changes that are made to the array will be reflected in the object that was passed.
What actually gets passed to modifyArray is a copy of the array reference, which is why people say Java is "pass by reference value".
What's happening is that when you pass array to modifyArray(int[]) is that array which is actually not a java primitive, so array2 is really still the same object as array.
A fairly easy way to copy the first array would be to use System's arrayCopy method like this
public static int[] modifyArray( int array[] )
{
int length = array.length; // length of the original array
int array2[] = new int[length]; // the new array which we will copy the data into
System.arraycopy(array, 0, array2, 0, length); // now we copy the data from array[] into array2[]
for ( int counter = 0; counter < array2.length; counter++ ) {
array2[ counter ] *= 2; // multiply by 2
}
return array2; // return the array with the new values
}
You now have a copy of the original array, but with all the values multiplied by 2.
I hope this helps.
public class PassArray
{
public static void main( String[] args )
{
int[] array = { 1, 2, 3, 4, 5 };
System.out.println(
"Effects of passing reference to entire array:\n" +
"The values of the original array are:" );
for ( int value : array )
System.out.printf( " %d", value );
modifyArray( (int[])array.clone(); ); // pass array reference to method modifyArray
System.out.println( "\n\nThe values of the modified array are:" );
// output the value of array (why did it change?)
for ( int value : array )
System.out.printf( " %d", value );
} // end main
// multiply each element of an array by 2
public static void modifyArray( int array2[] ) // so this accepts an integer array as an arguement and assigns it to local array array[2]
{
for ( int counter = 0; counter < array2.length; counter++ )
array2[ counter ] *= 2;
} // What hapened here? We just made changes to array2[] but somehow those changes got applied to array[]??? how did that happen?
//What if I wanted to not make any changes to array, how would implement this code so that the output to screen would be the same but the value in array would not change?
}
Please read this link to understand better
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 6 years ago.
I thought almost all languages, including java, pass array into function as reference (modifiable).
But somehow it does not work here, and the testArray is still 1,2,3 with size of 3.
Strange enough, when if I change result[i] = 2 to a[1] =2 it works. It did pass by reference.
What is wrong with this code?
At the end, I had a = result; (which update the a). Did result get removed from stack. Is that why I still get to the original a?
I am confused.
Thanks!
class Test
{
public static void main(String[] args)
{
int[] testArray = {1,2,3};
equalize(testArray, 6);
System.out.println("test Array size :" + testArray.length);
for(int i = 0; i < testArray.length; i++)
System.out.println(testArray[i]);
}
public static void equalize(int[] a, int biggerSize)
{
if(a.length > biggerSize)
throw new Error("Array size bigger than biggerSize");
int[] result = new int[biggerSize];
// System.arraycopy(a, 0, result, 0, a.length);
// int array default value should be 0
for(int i = 0; i < biggerSize; i++)
result[i] = 2;
a = result;
}
}
The array is passed by reference, but the reference is passed by value. That is, you can change the array that a refers to, but you cannot change which array a refers to.
Java is pass by value. This is why your code does not work. A good practice would be to mark int[] a as final so this would result in a compilation error (see the corresponding Checkstyle rule).
return parameter "a" from the function and assign to testArray in the main function. When you pass an object by reference, the reference is copied and given to the function. So the object is now referenced by 2 references. Any changes in the object through the 2nd reference will reflect in the first reference, because it is the same object referenced by both of them. But when you change the reference (not the object through reference), it is a different case. you have changed the 2nd reference to point to another object(int[] result). So any changes through the 2nd reference will change only the "result" object.
class Test
{
public static void main(String[] args)
{
int[] testArray = {1,2,3};
testArray = equalize(testArray, 6);
System.out.println("test Array size :" + testArray.length);
for(int i = 0; i < testArray.length; i++)
System.out.println(testArray[i]);
}
public static int[] equalize(int[] a, int biggerSize)
{
if(a.length > biggerSize)
throw new Error("Array size bigger than biggerSize");
int[] result = new int[biggerSize];
// System.arraycopy(a, 0, result, 0, a.length);
// int array default value should be 0
for(int i = 0; i < biggerSize; i++)
result[i] = 2;
a = result;
return a;
}
}
When you do a = result; object a dosnt anymore point to the testArray, bc you are changing its reference to result's address. That's why it dosnt effect anymore to the testArray.
What you are doing actually is you are making a the same adress as result has, so whatever you change in a it will change in result too.
Hope this helped...
The array referenced by a can be modified, but the reference itself is passed by value. So if you did a[0] = 1, then you would be changing the original array. However, a = result changes the reference, and so the original reference is unchanged.
Java is pass by value, always.
Arrays are Objects in java. If you have initialized your array with a size(actually length), you cannot modify it. You can create a new Array with a varying size (as you are currently doing in the function ) and copy all the values from the Old Array to the new Array. In your case, you have 2 objects and 3 references. If you want to access the Array of greater size in the calling function , make the function return the reference of the Array of greater size.
public class test
{
public static void main(String[] args){
int[] a = {15, 2, -3};
printArray(a);
changeArray(a);
printArray(a);
}
private static void changeArray(int[] a){
for(int i = 0; i < a.length; i++){
a[i]++;
}
}
private static void printArray(int[] a){
for(int i = 0; i < a.length; i++){
System.out.print(a[i] + " ");
}
System.out.println();
}
}
-----OUTPUT-----
15 2 -3
16 3 -2