java array pass by reference does not work? [duplicate] - java

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

Related

Why this below code is not returning the desired output ? it should return 1,3,2,2,0,0,0 while its returning same array

When I run the below code it's returning same array as output. Can anyone tell me where I am wrong?
public class MoveZeroToend {
public static void main(String[] args) {
int[] arr = { 1, 3, 0, 2, 0, 2, 0 };
Move0Toend(arr);
}
static void Move0Toend(int[] arr) { // Code to move zeroes to end
int count = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] != 0) {
swap(arr[i], arr[count]);
count++;
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " "); // Print the array
}
}
static void swap(int a, int b) { // To swap
a = a + b;
b = a - b;
a = a - b;
}
}
on your swap method, you are not swapping the actual values of the objects you've passed, you are swapping between the values passed to the method but there is no result returned so nothing happens. you need to either do the swap on the actual objects - not in a method, or use another way for this. I would recommend googling "pass by value" and "pass by reference". I would also recommend adding a unit test or at least debug the program so you can validate your code is doing what you want.
Your swap method doesn't return any values, nor does it change the values in the reference of the objects passed. To fix this you can either return two values from your swap method (a and b) or you could do it not in a method, that way it would directly affect the objects.
Just for a little more explanation, the variables a and b in your swap method are local to the swap method, changing these would not affect any other variables, even if they were also named the same, and as your method is a void it can't return anything.
Hope this helps :)
Your swap() method isn't performing any operation on your array, you are just passing two values a and b and swapping them but no operation is being performed on your array.
Instead of passing these two values to your swap() method you can directly swap them inside your for loop as below:
for(int i=0;i<arr.length;i++){
if(arr[i]!=0){
int temp = arr[i];
arr[i] = arr[count];
arr[count] = temp;
count++;
}
}

Why an array reference is passed in the method instead of its values? [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 3 years ago.
I am declaring an array myArray in main method and passed the same array in doIt(myArray) method.
When I took another array variable in doIt() method and assign myArray to it. And then I printed the myArray in main method.
But I am doing same thing with integer and String, the changes made in respective method do not affect the output.
My Code is
public class ChangeIt {
public static void main(String[] args) {
int[] myArray = {1,2,3,4,5};
new ChangeIt().doIt(myArray);
for (int i = 0; i < myArray.length; i++) {
System.out.print(myArray[i] + " ");
}
String str= "Gaurav";
new ChangeIt().printString(str);
System.out.println("\n"+ str);
int num = 5;
new ChangeIt().printNum(num);
System.out.println(num);
}
private void doIt(int[] z) {
int[] A = z;
A[0] = 99;
}
private void printString(String s){
String s2 = s + "Kukade";
}
private void printNum(int x) {
int y = x+1;
}
}
The output is
99 2 3 4 5
Gaurav
5
So, what is happening? Why it is printing 99 instead of 1?
But I am doing same thing with integer and String, the changes made in respective method do not affect the output.
The fundamental difference is that with the int and String, you're not changing the state of the original int or String. In fact, you're not even assigning to the parameter (but if you did, it wouldn't be observable outside the function).
But with the array, you're changing the state of the array, not assigning a new array to a local.
This:
int[] A = z;
just points A at the same array z points to, it doesn't create a new array. Since they both point to the original array, assigning to one of its elements changes the state of the array.

array method issue in output [duplicate]

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.

Java Two Dimensional Array passed to method and not changed

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

Returning an Array

I am new to programming and Java and trying to write a program which takes two arrays as input and reports back their sum. I want to do this by creating a class which takes two arrays as constructor inputs and then creating a method that adds them together and a method which prints out this new sum array.
Here is my class:
public class test1 {
int [] a;
int [] b;
int [] final23;
public test1 (int x [], int y [])
{
int [] a = x;
int [] b = y;
}
public int [] sum(int [] x, int[] y)
{
int [] a = x;
int [] b = y;
for (int i = 0; i < Math.min(x.length, y.length); i++)
{
final23 [0]=x[0] + y[0] ;
}
return final23;
}
public void print()
{
for (int i = 0; i < final23.length; i++)
{
System.out.println(final23[0]);
}
}
}
Here is my main class:
public class main1 {
public static void main(String[] args)
{
int l[] = {4,7,2};
int k[] = {4,6,2};
test1 X = new test1(k,l);
X.sum(k,l);
X.print();
}
}
I keep getting an error when I run this through:
Exception in thread "main" java.lang.NullPointerException
at test2.sum(test2.java:17)
at main1.main(main1.java:8)
I guess what I really want is for my sum method to take a test1 object as input. However, I don't know how to do this.
Your variable final23 is never initialized.
In java you have to initialize an array before using it. Either you do it during the declaration (like you did with k and l) or you have to do it later with a new arrayType[arraySize];
Here are the way an array can be declared/initialized.
int[] iArray = {1, 2, 3}; //Declaration, Initialization, set values
int[] iArray; //Declaration
iArray = new int[3]; //Initialization
iArray[0] = 1; //Set value
int[] iArray; //Declaration
iArray = new Array[3]{1, 2, 3}; // Initialization and set values
You can of course for the two last sample put the initialization on the same line that the declaration.
Try this (cleaned) code :
public class test1 {
int[] final23;
public int[] sum(int[] x, int[] y) {
final23 = new int[Math.min(x.length, y.length)];
for (int i = 0; i < final23.length; i++) {
final23[i] = x[i] + y[i];
}
return final23;
}
public void print() {
for (int aFinal23 : final23) {
System.out.println(aFinal23);
}
}
public static void main(String[] args) {
int l[] = {4, 7, 2};
int k[] = {4, 6, 2};
test1 x = new test1();
x.sum(k, l);
x.print();
}
}
Resources :
Oracle.com - Arrays
JLS - Array Initializers
JLS - Array Creation Expressions
I'm going to take a long shot here
public int [] sum(int [] x, int[] y)
{
int [] a = x;
int [] b = y;
for (int i = 0; i < Math.min(x.length, y.length); i++)
{
final23 [0]=x[0] + y[0] ;
}
return final23;
}
As a side comment, I'm guessing that you want to add all of the elements of the vector, not just the first. Change your for-loop body to:
final23 [i]=x[i] + y[i] ;
What's final23? Where is it created?
Try adding this to your constructor
public test1 (int x [], int y [])
{
int [] a = x;
int [] b = y;
this.final23 = new int[Math.min(a.length, b.length)];
}
Now final23 is defined and created, and you can use it in your class.
If you supply test1 with arrays in the ctor, you don't need them in the sum method, just use the ones you have in the class already:
public int [] sum()
{
for (int i = 0; i < Math.min(x.length, y.length); i++)
{
final23 [i]=a[i] + b[i] ;
}
return final23;
}
You also had an error in the sumation, you didn't use the iteration variable, you also need to initialize final23 in the ctor.
You have to initialize final23 array before putting elements in it (on line 17).
**final23 = new int[Math.min(x.length, y.length)];**
for (int i = 0; i < Math.min(x.length, y.length); i++)
{
final23 [0]=x[0] + y[0] ;
}
I see a couple of things to point out here.
public test1 (int x [], int y [])
{
int [] a = x;
int [] b = y;
}
First of all, remember that each test1 object - that is, each instance of your test1 class - has variables named a and b. I'm guessing that in the constructor, you want to take the arrays x and y which were passed as parameters and store them into a and b of the object. To do that, all you have to do is write
a = x;
b = y;
You don't have to write int[] again, not when you just want to access an existing array-type variable. You only write that when you're creating a new array-type variable. In this case, when Java sees that you've written int[] a in the constructor, it thinks you want to create yet another array-type variable named a, separate from the one in the test instance, and that's the one that gets set equal to x. The thing is, that local variable gets lost at the end of the constructor. So you're left with a test1 instance that has variables a and b that still refer to nothing, i.e. they're null.
By the way, since you're going to be using the array final23 later on, you should initialize it. Right now, it refers to null because you never set it to equal anything else. You'll need to create a new array and store it in that variable in order to be able to use it later on. So put this line in your constructor:
final23 = new int[Math.min(a.length, b.length)];
That creates the new array with a length equal to the shorter of the two arrays passed in.
Moving on:
public int [] sum(int [] x, int[] y)
{
int [] a = x;
int [] b = y;
In this bit of code, you have the same issue as in the constructor: you create two new array-type variables a and b that get used instead of the ones in the test1 object. I don't think that's what you meant to do. So I'd say get rid of those last two lines entirely.
There's another problem, though: if you think about it, you still have two arrays stored in the test1 object. Assuming you've fixed your constructor, those are the same two arrays that were passed to the constructor. And now you're getting two new arrays under the names x and y. So you have four arrays total. Which ones did you want to sum up? I'm guessing that you meant to sum the two arrays that were passed to the constructor. In that case, your sum method doesn't need to - and shouldn't - accept more arrays as parameters. Get rid of the parameters x and y, so your sum method just looks like
public int [] sum()
{
Now you have to change the rest of that method to use a and b, starting with the for loop. Change its opening line to this:
for (int i = 0; i < Math.min(a.length, b.length); i++)
{
I notice you were wondering how to get your sum method to take an instance of test1. Well, in a way it actually does. There's a special hidden parameter passed to all methods (except static ones) that contains the object the method was called on - in fact, using your main program as an example you could kind of think of X.sum(k,l); as actually calling test1.sum(X,k,l);, where X is the special hidden parameter. You can access it inside the method using the name this (so you could write this.a instead of just a), but Java is generally smart enough to do that for you.
In the body of the for loop, you have another problem. What you want to do is add up corresponding elements of the arrays, i.e. a[0] + b[0] goes into final23[0], a[1] + b[1] goes into final23[1], and so on. But inside the for loop, you only ever add up element 0 of each array. You need to use the loop index variable i, because that runs through all the values from 0 to the length of the shorter array minus 1.
final23 [i] = a[i] + b[i];
}
return final23;
}
So the first time the loop runs, i will be 0, and you'll set final23[0] = a[0] + b[0]. The next time it runs, i will be 1, and you'll set final23[1] = a[1] + b[1]. And so on.
The same problem occurs in your print method. Each time through the loop, you always print out final23[0], when you really should be printing out final23[i] because i changes each time you go through the loop. Change it to
public void print()
{
for (int i = 0; i < final23.length; i++)
{
System.out.println(final23[i]);
}
}
At this point your program should be working, I think, but there are still some improvements you could make to its design. For one thing, every time you create an object of test1, you know you're immediately going to call sum on it. So why not just put the summing-up code right into the constructor? That way you know that the sum will be computed right when you create the object, and you don't have to call sum explicitly.
Of course, once you do that, you'll have no way to access the array final23 from your main class - except that if you want to print it, you can call the print method. But what if you want to write a main class that, say, adds up two arrays, and then adds the result to a third array? It'd be nice to have a way to get the result from the test1 instance. So you can add an accessor method, possibly named getFinal23, that just returns the sum array final23.
In practice, this operation of adding two arrays would probably be implemented as a static method. So if you want, you could try starting over, and writing it as a static method. (Remember that a static method is one which doesn't receive a special hidden parameter) Inside the static method, you'd have to create the final23 array, go through the loop to compute the sums, and then return the array you created. You'll need to enclose the static method in a class, of course, but that class doesn't have to have a constructor since you never really use it for anything. It'd look something like this:
public class SumClass { // pun intended ;-)
public static int[] sum(int[] x, int[] y) {
// you fill in this part
}
}

Categories