Why do arrays change in method calls? [duplicate] - java

This question already has answers here:
Are arrays passed by value or passed by reference in Java? [duplicate]
(7 answers)
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed last month.
When I write like this:
public class test {
void mainx()
{
int fyeah[] = {2, 3, 4};
smth(fyeah);
System.out.println("x"+fyeah[0]);
}
void smth(int[] fyeah)
{
fyeah[0] = 22;
}
}
It prints x22;
When I write like this:
public class test {
void mainx()
{
int fyeah = 5;
smth(fyeah);
System.out.println("x"+fyeah);
}
void smth(int fyeah)
{
fyeah = 22;
}
}
It doesn't print x22, but prints x5.
Why, in the second version function, doesn't the value change? Does it change values only for array elements?

The fyeah variable in your first example contains a reference to an array (not an array), while the fyeah integer in your second example contains an integer.
Since Java passes everything by value the following will happen:
In the array case: A copy of the array reference will be sent, and the original array will be changed.
In the int case: A copy of the integer will be changed, and the original integer will not be changed.

It's because your int is a primitive and the method smth creates a local copy which is why it doesn't print the way you want. Objects are passed by value as well, but a value to the pointer in memory. So when it is changed, the pointer stays throughout both methods and you see the change. Read More Here

Ok. An int in java ( and really all languages that have strict data typing ) is a primitive data type. Its just a single variable of that data type. In java this means its passed by value to the method. So when you pass in the argument, a copy of the passed variable is created. Any operations that take place in the method act on that copy not the passed variable.
Actually in java EVERYTHING is passed by value but getting into the details of how that actually is true with what I am going to say next seems inadvisable.
With the array...its a collection of variables of the primitive data type int. So an entire copy of the array isn't actually made just a copy of the reference to the memory that stores the array. so yes the value of the int IN the array is changed from operations in the method.
In short methods don't change the external value of primitives (int,float,double,long,char) with the operations in the method, you have to return the resulting value of those operations to the caller if you wish to obtain it. Operations do change the value with most objects as well as with arrays of primitives. Hope that helps. Really unsure of how low level to get. Maybe someone else can clearly explain exactly why its by value. I "get" it but find it hard to help other people understand.

Think it in terms of memory: Lets analyse your first program -
In mainx , fyeah is an array of ints , so its a reference ( or a pointer if I may ). This reference points to a location in heap memory where the actual array of ints is stored. Lets say at address 100. Located contiguously from here are three ints ( lets say beginning at address 100 , 104 and 108 respectively are 2 ,3 and 4 ).
Now you call your method smth and pass the reference. Within the method , there is another reference ( of an int array type ) named fyeah. This fyeah is quite distinct from fyeah reference in the mainx method. Now , when you call smth and pass the fyeah from mainx , the fyeah within the smth method is initialized to point to the same location ( ie memory address 100 )
When you access the 0 element of fyeah and assign it a value of 22 , it reaches out to the memory location of 100 and writes this value 22 there. When you come back in your mainx method , the fyeah reference is still referring to memory address 100. But the value present at that location is now 22. So you get that value when you access the first element from fyeah in mainx.
Now , your second program. Your mainx method declares an int ( not an array , but a simple int ) and set it to 5. This fyeah variable is created on stack not on the heap. The value of 5 is stored on the stack. Now you call smth and pass this variable. Within the method smth , you again declare an int variable , fyeah by name ( as a formal method argument ). Again this is distinct from the fyeah of the mainx method and this fyeah is also created on stack.This variable will be initialized to a value of 5, copied over from the fyeah you passed to smth as argument. Note now that there are two distinct copies on fyeah variables , both on stack , and both a value of 5. Now you assign the fyeah in smth a value of 22. This will not affect the fyeah of the mainx method,so when you return to mainx and access fyeah , you see 5.

The int is a value type so 5 is passed directly into smth which can only modify the local copy. An array on the other hand is a reference type so the elements of that array can be modified.

Seeing it a bit less technically, I would say that
fyeah[0] = 22;
is changing the content of (the object pointed to by) fyeah, while
fyeah = 22;
is changing (the variable) fyeah itself.
Another example:
void smth(Person person) {
person.setAge(22);
}
is changing (the content of) the person while
void smth(Person person) {
person = otherPerson;
}
is changing the variable person - the original instance of Person is still unchanged (and, since Java is pass-by-value, the variable in the calling code is not changed by this method)

Related

Don't understand error message (required: variable, found: value)

The error message pertains to this line of code
Player a = pl.get(i);
/*
* CODE MODIFTYING VARIABLES WITHIN THE OBJECT a
*/
pl.get(i) = a;
'pl' is an ArrayList of the class Player
this code is in a for loop where 'i' is equal to the number of intervals the for loop has gone through
it specifies that "(i)" is a variable an it should be a value, what does it mean by value???
Basically, I'm copying my Player object in my array list and setting it to a Player object variable that is created within the for loop and changing the values within the object and then setting the newly created object (Player a) to my index in the ArrayList (pl.get(i))
I'm doing this so I don't have to keep writing pl.get(i).getFunction() pl.get(i).setFunction() pl.get(i).CalculateFunction() pl.get(i).blablabla();
I can just use a.whatever = 83465;
So the question is, what am I missing?
pl.get(i) is a value type (rvalue) and can not be assigned a new value.
Only lvalues can be assigned values.
You have to use the set method of ArrayList to overwrite values in the list:
pl.set(i, a);
Additionally, when calling pl.get(i) to retrieve the element you named a, you can use this reference to change a in any way you want. you don't have to write the object back into the list, as the reference is still there.

mutate array in JAVA

public class example
{
public static void main(String[] args)
{
int[] MyArray = new int[10];
MyArray[1] = 5;
int[] NewArray = MyArray;
NewArray[1] = 10;
System.out.println(MyArray[1]);
}
}
Why does the system print out 10 instead of 5?
It seems like whatever changes we made to element in NewArray, MyArray will change along, why?
I copy this pattern to initiate like int, string variables but they don't behave like this above, why? thanks guy, I am new to CS programming.
It seems like whatever changes we made to element in NewArray, MyArray will change along, why?
You aren't changing NewArray. You're changing the array that the value of NewArray refers to. It's like this:
NewArray is a variable (an unconventionally named one, but hey)
The value of NewArray is a reference
The reference refers to an object
It's really, really important to differentiate between variables, references and objects. Don't feel worried that it didn't just come to you immediately - this is a stage a lot of people go through when they first encounter a language like Java.
The values of MyArray and NewArray both refer to the same array, so if you make changes to the array via one variable, you still see the change when you then look at the array via a different variable.
I copy this pattern to initiate like int, string variables but they don't behave like this above, why? thanks guy, I am new to CS programming.
For int, that's a value type - the value of an int variable is the number itself, not a reference to an object.
For String, I suspect you were changing the value of the variable to refer to a different String object - not changing the contents of the String object itself (which you can't - strings are immutable in Java). For example:
String x = "first";
String y = x;
x = "second"; // This doesn't change the value of `y`
I like to think of variables as pieces of paper. For value type variables, the value is just written on the piece of paper:
int i = 10;
is like having a piece of paper with the name i, and a value of 10 on it.
For classes and arrays (which are reference types) the value on the piece of paper isn't the object - it's a way of navigating to the object. A bit like having someone's home address written on a piece of paper.
Suppose you have two pieces of paper with the same address written on them. If you rub one of them out and write a different address, that doesn't change anything about what will happen if someone looks at the other piece of paper and goes to that house. That's like the String example above.
The array example, however, is more like this: I write my home address on two pieces of paper, and give them to Fred and Ginger. Fred reads the address, visits my home, and paints the front door red. (He's modifying the object - my house - without changing his piece of paper at all.) Now if Ginger reads the address on his piece of paper and visits my home, he'll see a red front door.
The reason this happens is because when you say int[] NewArray = MyArray; this is copying the reference of MyArray to NewArray.
This reason you are copying the reference is because you do not call the new operator to instantiate a new array.
So, when you say NewArray[x] it is pointing to the x position in memory of MyArray (and hence the value in memory of MyArray). No new memory is allocated when you do int[] NewArray = MyArray; since the new operator is not called.
It is beacuse when you do =, this makes the new obkect to point to the old one. So any changes made to the new one will reflect in the old one to, as they are the same technically.
You should array.clone to avoid this.
You are not copying it's value. You say:
Java create "MyArray".
Java creates a variable poiting at an object
Java create another array "NewArray" that is the same as MyArray
Java creates a variable poiting at the same object as MyArray
Java change the value of NewArray[1] to 10
Java changes the value on the object it is poiting at, not the variable itself.
Hope you get it.
As a side note, you should use [0] instead of [1]. Arrays start at 0, like everything in programming. So, the array with 10 items you created starts at 0 and ends at 9. Take note of that.

Object Instance Manipulation

If I have an Object instance, say a4, is there a way I could print out the name of the instance?
So with the instance a4, I would like my output to say a4.
Not stalking you I swear!
Short answer: No
Long Answer: Its impossible to get the name of a local variable using the reflection API as it is simply not available to the JVM. Have a look here: Java Reflection: How to get the name of a variable?
Its a hideously messy thing to attempt to do. Why are you trying to do it?
The simple answer is; if you want an object to have a name, give it a name field and add this field to the toString()
Local variables are only available in the debug information of a method. It is possible to read the byte code of a method and reverse engineer a name but this requires an extraordinary amount of work.
Consider
Object a1 = ...
Object b1 = a1;
The same object is referenced by two local variables. An object can be referenced in any number of places. e.g the empty string object is often the most referenced object in a Java program. It can appear in 10Ks places in a normal program.
I'm trying to add an array to a HashMap using a method that is only passed in a HashMap key. I take the key, extract an array already in the HashMap, make a clone of it, and then place that clone in the HashMap using the name of the instance as the key.
Say you pass an array into a method like
public void addArray(int... array) {
At this point the "name" of the reference to the array is array and it will not be anything difference.
What you need is to pass the name you want the array to have as there is no way for a caller to know what the callee used as a local variable. Often a variable has no name in the first place.
addArray(1, 2, 3);
or
addArray(calculateNumbers());
or
int[] nums = { 1, 2, 3 };
addArray(nums);
Note: nums is not actually needed as a local variable can be optimised away. i.e. There is a good chance nums won't even exist at runtime.
What you need to do is
public void addArray(String name, int... array) {
map.put(name, array);
}

Changing array in method changes array outside [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Are arrays passed by value or passed by reference in Java? [duplicate]
(7 answers)
Closed 9 years ago.
I have trouble with scope of variable.
public static void main(String[] args){
int[] test={1,2,3};
test(test);
System.out.println(test[0]+" "+test[1]+" "+test[2]);
}
static void test(int[] test){
test[0]=5;
}
I expected the output to 1 2 3, but the result was 5 2 3.
Why I changed the value in the array in the method, but the original array changed?
An array in Java is an object. When you create an array via new, it's created on the heap and a reference value (analogous to a pointer in C) is returned and assigned to your variable.
In C, this would be expressed as:
int *array = malloc(10 * sizeof(int));
When you pass that variable to a method, you're passing the reference value which is assigned (copied) to the local (stack) variable in the method. The contents of the array aren't being copied, only the reference value. Again, just like passing a pointer to a function in C.
So, when you modify the array in your method via that reference, you're modifying the single array object that exists on the heap.
You commented that you made a "copy" of the array via int[] temp=test ... again, this only makes a copy of the reference value (pointer) that points to the single array in memory. You now have three variables all holding the same reference to the same array (one in your main(), two in your method).
If you want to make a copy of the array's contents, Java provides a static method in the Arrays class:
int[] newArray = Arrays.copyOf(test, test.length);
This allocates a new array object on the heap (of the size specified by the second argument), copies the contents of your existing array to it, then returns the reference to that new array to you.
Definitions:
Reference = A variable that points to the location in memory where your array lives.
Value of a Reference = The actual memory address location itself
You passed the value of the reference of your array into your test() method. Since java is Pass By Value, it passes the value of the reference, not the value of your array (ie. a copy).
It may be easier to think of a reference as a pointer if you have a C background. So a value of a reference is essentially it's memory address (I'm fudging java rules here but it may be simplest to think of it this way)
So, in your example, you pass the value of the reference which points to your array, into your test() method, which then uses that reference value to lookup where your array is in memory, so it can access data in your array.
Since in your test() method you do not change your array's reference (where it points to, ie. test = new int[10];), then your test() method acts on the original data in the array (because it still points to your original array's location), leading to element 0 being set to a value of 5.

When does a 'void' method affect the parameter, and when does it affect the original object?

I am brand new to programming, as well as to this website, so forgive me if I screw anything up. I'm having a heck of a time figuring out how to properly post my code in here.
package tester;
import java.util.*;
public class Mainclass2 {
public static void main(String[] args) {
int y = 3;
int[] x = {1, 2, 3, 4};
editnumbersArray(x);
editnumbersNotArray(y);
System.out.println(x[2]); **//now this was changed from 3 to 9...**
System.out.println(y); //but this one went unchanged.
}
//this accepts 'x[]' into the 'a[]' parameter.
public static void editnumbersArray(int[] a){
a[2] = 9; **//<---why does this one CHANGE the actual x[2] instead of just a[2]?**
}
//this accepts 'y' into the 'a' parameter.
public static void editnumbersNotArray(int a){
a = 9; **//<--while this one only changes 'a' instead of 'y'?**
}
}
So my question is basically typed in there as comments. Why does the array that is passed into the method change the values of the original array (x[]) when the int that is passed into the other method doesnt change? I'm sure it's a simple answer, but when I did my research I couldn't figure out what to search. I don't know what this is called so everything I searched led me the wrong way. Thanks for any help!!
EDIT: Thanks for that analogy with the address! That is by far the best way you could have explained it to me. So basically when you pass an array into a parameter, its passing a reference, not the actual value? So when I make adjustments within my method, its changing whatever the array is referencing?
I noticed that this also happens with a list. So the list isnt actually passed by value? It seems as if the array/list itself is basically passed in for editing, no matter what I name it within my method (a[] in this case.)
EDIT http://javadude.com/articles/passbyvalue.htm this page really cleared it up. And sorry for posting a duplicate question. The problem was that I didn't know what I was trying to ask. I had never even heard these terms "pass-by-value/reference", so now I know
Changing the value of the parameter itself never affects the argument in Java, because all arguments are passed by value. However, look at this method:
public static void editnumbersArray(int[] a){
a[2] = 9;
}
That assignment doesn't change the value of the parameter. The value of a is still the same reference, to the same array - it just changes the contents of the array.
Imagine if I wrote my home address on a piece of paper for you. It wouldn't matter what you did to that piece of paper - that wouldn't change where I lived. However, if you visited the address and painted the front door green, without ever changing the piece of paper at all, I would see that change.
It's very important to differentiate between different concepts:
A variable is a named storage location; it holds a value, which is always either a primitive value (e.g. an int) or a reference. In my example above, the piece of paper was like the variable.
A reference is just a value which allows you to navigate to an object. It's not the object itself. It's like the address on the piece of paper.
An object contains other variables. There may be several variables which all have values which are references to the same object. It's like the house in my example: I can write my address on several pieces of paper, but there's only one house.
An array is an object which acts as a container for other variables. So the value of a is just a reference to the array.
Java uses pass by value (what you want to search for) for everything. Essentially that means it makes a copy of the parameter that it then passes to the method. That means that you cannot change what something points at by using the = operator.
That is why the (int a) version doesn't change a.
However, in the case of an Object or an array it doesn't make a copy of the Object or array, it makes a copy of the reference to the Object or the array. That means that you have two variables, the original on and the, in your example, (int[] a) one that both point to the same spot in memory. Changes to either variable will affect the other variable.
Pass by value, pass by reference, and pass reference by value are the types of things you want to search on for more information.

Categories