First of all, I understand what's so called passing by value in Java.
Also I understand, when you pass an object or an array, it is the array's address that is passed into the method. So modifying the array variable inside the method will affect the outside array variable.
For example,
private void change(int[] a) {
a[0] = 1234;
}
public static void main(String[] args) {
int[] a = new int[2]{1,2};
change(a);
System.out.println(a[0]);
}
The output will be 1234, because the a inside change is actually the array outside.
What I don't understand is the following code:
private void change(int[] a) {
a = new int[3]{1234, 4, 5};
}
public static void main(String[] args) {
int[] a = new int[2]{1,2};
change(a);
System.out.println(a[0]);
}
Why the output is 1, not 1234?
The inside a was the same thing as outside a, right? I also modify the inside a just like the example above did, why two different output?
This is not the same. In your second example, you are changing the local reference a to refer to a completely new array, not changing the existing array. But this does not change the a in main to refer to the new array; it still refers to the old array, so 1 is printed.
If you wanted to re-assign a completely new array to the a in main using a method, then return the new array from change and assign that to a in main.
Let's inspect your function:
private void change(int[] a) {
a = new int[3]{1234, 4, 5};
}
As you stated in your question, a is a reference to an array. If you use it to modify the array (e.g., a[0]=1234), you will be changing the same array that was passed in to the function.
However, if you change the reference itself, a will no longer be pointing to the original array, and changes to it will not affect the original.
This is exactly because the reference is passed by value. We'll represent object pointers with 5-digit numbers like 12345. The process is as follows:
We create an int[]{1,2}, at memory location, say 10000. We assign a the value 10000. a is on the stack frame corresponding to main.
We pass the value 10000 to change.
change executes:
change creates a new array at location 20000 and sets the value of a on its stack frame to 20000. This does not affect the main stack frame.
change returns (void).
We deference the untouched pointer to the original array in order to print the zeroth element, 1.
Note that by the time change returns, we have no live references left to {1234, 4, 5}.
In Java all variables are references to objects.
When you pass a variable into an array, you pass the reference to the object. If you modify the object then the calling method - which also has a variable that refers to the same object - sees the change.
When you write "a = new int..." you are changing the value of the variable a to point to a different object. It is no longer referring to the same object as the one in the method that called it. So the calling method and the called method see different things.
When you pass a parameter by value, it basically means that it's copied from a method's point of view. So, you have a reference a to an array, and when you pass it to some method, inside that method you have another reference, also named a to the same array. Now, when you assign a new value to that reference (a = new int[]...) you are only modifying the local a variable to point to a new array.
The answer has as much to do with passing by reference or value as it does with which variables are in scope when you attempt to make the change.
When you pass "a," or any variable to a method, you pass the value of that variable - in other words a copy of what it represents- and not the actual variable itself. For example:
public static void main(String[] args){
int a = 3;
addTwo(a);
System.out.println(a);
}
private void addTwo(int a){
a += 2;
}
In the above example the value 3 is passed to addTwo. The variable "a" in the main method is outside of its scope (i.e. it is localized to the main method) so the addTwo method acts only on the copy of "a," the value 3, and not the variable. The variable "a" remains unchanged. When the method completes the value of a is discarded and the original "a" in the main method remains unchanged.
This is the same thing that is happening in your case. It does not matter that you use the same name for two variables. The variable in your main method will not be changed.
Related
I am confused why the hello method is able to affect the array declared in the main method. My understanding was it was outside of the scope.
public class Test {
void hello(String i, int[] arr){
i += "hello";
arr[0] = 4;
}
public static void main(String args[]){
Test t = new Test();
String i = "hey";
int [] arr = {0,1,2,3};
t.hello(i,arr);
System.out.println(i);
System.out.println(Arrays.toString(arr));
}
}
returns
hey
[4, 1, 2, 3]
i would understand a return of "heyhello" or [0,1,2,3].
There's an important difference between String and int[].
Both are so-called "reference objects", meaning that they hava a unique identity, and can be referenced from variables, fields, method arguments etc.
So, t.hello(i,arr) passes two arguments into the hello() method:
a reference to a String with content "hey"
a reference to an int[] array with content {0,1,2,3}.
Inside hello(), you "modify" both variables, but differently:
With i += "hello";, you append a word to the end of the string. The Java designers decided to make strings "immutable", so you can't change a String object that has been created, you can only create a new string in such a case. That means that the original string (that the i variable from main() still references) will not be affected. It's only the i inside hello() that now references the fresh, longer string. And main() still has its i being "hey".
With arr[0] = 4;, you set the first array element to a different value. Arrays have been defined differently, they are mutable. For an existing array, you can modify its elements without the need for a fresh copy. So, there's still only one array in use, and its first element has been modified. When main() prints its arr array, it is the identical array that has been modified inside hello(), und thus contains the number 4.
The posted code is demonstrating the difference between passing mutable objects and immutable objects as parameters.
The array arr is passed to hello as an argument. That means the pointer to the arr object is copied and the copy is given to hello, so hello has a pointer to the array declared in the main method. Arrays are mutable and hello has a reference to it,, nothing stops hello from changing the contents of arr.
The string i gets passed into hello similarly, hello gets a copy of the pointer. The hello method replaces the string referred to by its copy of the pointer (since strings are immutable), but the pointer used by the main method is unaffected and still points to the original value of i.
Why is there a difference between the following two programs A & B. Shouldn't they run identical? For some reason the changer in the case of the array is changing the original value of the input array.
Program A:
public static void changer(int tester) {
tester = tester*2;
}
public static void main() {
int value = 1;
out.println(value);
changer(value);
out.println(value);
}
which gives me the output:
1
1
Program B:
public static void changer(int[] tester) {
tester[0] = tester[0]*2;
}
public static void main(){
int[] value = {1};
out.println(value[0]);
changer(value);
out.println(value[0]);
}
which gives me the output:
1
2
Changing a value in a called method does not change the value in the calling method. In Program B, you're not changing the array, you're changing a value inside the array, and that is visible in the calling method.
In your first example, you passed an int (tester) to the function, and then assigned a new value to it. Since java is pass-by-value, assignment has not effect outside of the callee scope, and so the original value was not changed in the call site.
In the second example, you passed an int array to the function, and then you did not assign to it, but modeified its content, by assigning to a specific cell inside of it, so the value was changed in the call site as well.
Passing primitive data type ( i.e int, double, long, float, ....) to a function or method will be " PASSED BY VALUE". In program A, the argument passed to method is a primitive data (int), so you just passed a copy of the origin value. Any change to it, will not affect the origin number.
But passing Reference/Object data type (i.e, Array, ArrayList, HashMap,...) to a function will be " PASSED OBJECT BY VALUE," which means the method is given copy of the reference to the object. So any change to it, will change the origin reference. In program B, you passed a reference copy of an array. That is why it has been modified.
When arrays work like pointers. When you use
tester[0] = tester[0]*2;
You are basically telling compiler to update element in memory on location tester[0]
This question had been asked so many times. Java passes everything by value and this is especially true for primitive such as int.
When you pass an int argument, you are passing in the value, not the reference of the variable.
public static void main(String[] args){
int value= 5;
changer(val);
}
public static void changer (int tester){
//A variable call tester holding the value of 5
}
A local variable call tester with value of 5 will be created, because you passed in a value of 5. Variable val itself was not passed in.
Any changes done within the method is merely changing the local variable tester.
This explains why the value of val remains unchanged.
When you pass in an array, it still passes by value, but the value does not contain all the values of individual array element. It will be very inefficient to copy the entire array's value for every method invocation. The value holds the reference of the array. Thus, tester now holds the reference of the val.
public static void main(String[] args){
int[] val= 5;
changer(val);
}
public static void changer (int[] tester){
//A variable call tester holding the reference of val array.
}
Since tester is now pointing at the original array: val. Anything you changed in the method will affect the original array.
I am trying to understand the difference between Object with primitive variables when using them as parameters in a method.
There are some examples using reference variables:
public class Test1 {
public static void main(String[] args) {
int[] value = {1};
modify(value);
System.out.println(value[0]);
}
public static void modify(int[] v) {
v[0] = 5;
}
}
result: 5
public class Test2 {
public static void main(String agrs[]) {
Integer j = new Integer(1);
refer(j);
System.out.println(j.intValue());
}
public static void refer(Integer i) {
i = new Integer(2);
System.out.println(i.intValue());
}
}
result: 2 | 1
So what is different in here?
In java array is primitive type.and Integer is Object type.
For primitives it is pass by value the actual value (e.g. 3)
For Objects you pass by value the reference to the object.
In first example,
you are changing value in array.
while in other example ,
you are changing reference of i to other memory location where object value is 2.
when returning back to main function, as you are not returning value. its reference scope limited to "refer" method only.
Recall that the array references are passed by value. The array itself is an object, and that's not passed at all (That means that if you pass an array as an argument, your'e actually passing its memory address location).
In modify() method, you're assigning 5 to the first place in the array, hence, changing the array's value. So when you print the result, you get: 5 because the value has been changed.
In the second case, you're creating a new Object of type Integer locally. i will have the same value when you exit the method refer(). Inside it you print 2, then you print i, which is 1 and hence change doesn't reflect.
v[0] = 5, is like saying Get 0th element of current v's reference and make it 5.
i = new Integer(2), is like saying change i to 2's Integer object reference
In one case you are changing the internal values via the reference and in latter you are changing the reference itself.
The difference here is that they are different.
In your first example you are passing the argument to another method, which is modifying one of its elements, which is visible at the caller. In the second case you are assigning the variable to a new value, which isn't visible at the caller, because Java has pass-by-value semantics.
NB 'Primary variable' has no meaning in Java.
I don't know what the word 'advance' in your title has to do with anything.
This question already has answers here:
Changing array in method changes array outside [duplicate]
(2 answers)
Closed 3 years ago.
public class Test {
public static void main(String[] args) {
int[] arr = new int[5];
arr[0] = 1;
method(arr);
System.out.println(arr[0]);
}
private static void method(int[] array)
{
array[0] = 2;
}
}
After invoking method, arr[0] becomes 2. Why is that!?
You can call set methods on objects passed to a method. Java is pass by value, which means that you can't replace an object in a method, though you can call set methods on an object.
If Java were pass by reference, this would pass:
public class Test {
public static void main(String[] args) {
Test test = new Test();
int j = 0;
test.setToOne(j);
assert j == 1;
}
public void setToOne(int i) {
i = 1;
}
}
Java is Pass-by-Value, Dammit! http://javadude.com/articles/passbyvalue.htm
This is because Java uses Call by Object-Sharing* (for non-primitive types) when passing arguments to method.
When you pass an object -- including arrays -- you pass the object itself. A copy is not created.
If you mutate the object in one place, such as in the called method, you mutate the object everywhere! (Because an object is itself :-)
Here is the code above, annotated:
public static void main(String[] args)
{
int[] arr = new int[5]; // create an array object. let's call it JIM.
// arr evaluates to the object JIM, so sets JIM[0] = 1
arr[0] = 1;
System.out.println(arr[0]); // 1
method(arr); // fixed typo :-)
// arr still evalutes to JIM
// so this will print 2, as we "mutated" JIM in method called above
System.out.println(arr[0]); // 2
}
private static void method(int[] array)
{
// array evaluates to the object JIM, so sets JIM[0] = 2
// it is the same JIM object
array[0] = 2;
}
Happy coding.
*Primitive values always have call-by-value semantics -- that is, a copy is effectively created. Since all primitive values are immutable this does not create a conflict.
Also, as Brian Roach points out, the JVM only implements call-by-value internally: the call-by-object-sharing semantics discussed above are implemented by passing the value of the reference for a given object. As noted in the linked wikipedia article, the specific terms used to describe this behavior differ by programming community.
Additional:
Pass by value or Pass by reference in Java? -- see aioobes answer and how it relates with Brian Roachs comments. And aioobe again: Does array changes in method?
Make copy of array Java -- note this only creates a "shallow" copy.
Because that's exactly what you're telling it to do. Java passes first by value, then by reference. You're passing in the array, but any modifications you make to that array will be reflected on any other accesses to that array.
A quick example for thought:
If within method you did array = null, no change would be visible from main - as you would be changing the local value of array without modifying anything on the reference.
Because when you are passing argument like int/double/char etc. they are the primitive data types and they are call by value - meaning their values are copied to a local variable in this method (that has the same name as the names in your argument) and changes made to them are only changes made to these local var -> does not affect your primitive type variables outside the method
however an array or any object data type is called by reference -> the argument pass their address(reference) to method. that way, you still have a local variable named by them which has the reference. You can change it to reference another array or anything. but when it is referencing an array, you can use it to set the value of the array. what it does is accessing the address it is referencing and change the content of the referenced place
method(arr[0]);
I think that's supposed to be
method(arr);
But anyway the value passed as argument to the method is the reference to the array and the local variable arr in the method is referencing the same array. So, within the method you are making changes to the same array.
Java is pass by value. What confuses people is that the 'value' of a variable that refers to an object allocated on the heap is a reference, so when you pass that, you pass the reference 'by value' and therefore it refers to the same object on the heap. Which means it doesn't matter from where you modify the referent; you're modifying the same thing.
I have an array of type string which I want to re-use inside a method.
I need to pass it to a function which returns a subset of the elements of array passed. To capture the returned array from function, should I declare a new string array or can I safely re-use same array that was holding the unfiltered array to hold filtered array ??
Also clarify that, when I pass a variable like array to a function does it creates a new space for the array in the heap each time I pass it as parameter to further functions or just it uses the same space in the heap & just passes the reference? I guess in case of array it passes just the reference but in case of simple variables it allocates new space on stack, right?
EDIT: Thanks you all for the great answers and explanations!!
Please also clarify whether that if I am reusing the array, would I be required to set the null at the position when I end the subset of array ? (Actually the subset of my array is not directly calculated from the array but some other calulations, so I would be required to manually set the null otherwise the older elements of the list would be visible, right??)
when I pass a variable like array to a function does it creates a new space for the array in the heap each time I pass it as parameter to further functions or just it uses the same space in the heap & just passes the reference
Java is entirely pass by value, but with arrays and object types, the value being passed is a reference (pointer) to the actual object, which is not duplicated. So when you pass an array into a function, only the reference to the array is copied; the array itself isn't. That's why if a function modifies the contents of an array, the code calling the function sees the modifications.
Example:
// A method that changes the first entry in an array
void changeArray(String[] theArray) {
theArray[0] = "Updated";
}
// A method that uses the above
void someMethod() {
String[] foo = new String[3];
foo[0] = "Original 0";
foo[1] = "Original 1";
foo[2] = "Original 2";
this.changeArray(foo); // `changeArray` receives a *copy* of the reference
// held in `foo`; both references point to the same
// array
System.out.println(foo[0]); // Prints "Updated"
}
Passing a reference into a method is exactly like assigning it to another reference variable:
String[] foo = new String[3]; // Create a new aaray, assign reference to `foo` variable
String[] bar = foo; // Copy the reference into `bar` as well
foo[0] = "Hi there"; // Use the reference in `foo` to assign to the first element
System.out.println(bar[0]); // Use the reference in `bar`, prints "Hi there"
Essentially, references are values (numbers) that tell the JVM where the data for an object is. So even when we copy a reference (because Java is entirely pass-by-value, the value of the reference is passed to the function), it still points to the same memory as the original.
Since the reference is passed into the function by value, the function can't change the calling code's reference:
// A method that assigns a new reference; the calling code sees no change
void changeReference(String[] theArray) {
theArray = new String[1]; // Now we're not using the caller's object anymore
theArray[0] = "I was changed";
}
// A method that uses the above
void someMethod() {
String[] foo = new String[3];
foo[0] = "Original 0";
foo[1] = "Original 1";
foo[2] = "Original 2";
this.changeReference(foo);
System.out.println(foo[0]); // Prints "Original 0", our reference wasn't changed
}
You'll note that this is exactly how primitives are treated:
void whatever(int a) {
a = 5;
}
void someMethod() {
int foo;
foo = 3;
whatever(foo);
System.out.println(foo); // Prints 3, of course, not 5
}
...and in fact, object references (as opposed to objects) are primitives.
...should I declare a new string array or can I safely re-use same array that was holding the unfiltered array to hold filtered array
You can safely re-use it if that's appropriate within the scope of your function. It may be more appropriate to declare a new variable (e.g., filteredThingy), but that's a matter of style and will depend on the situation.
You probably can by it is very bad style and is very error prone and is very unsafe for future modifications.
Here is the example.
public void foo(String[] args) {
// do something with array.
args = new String[] {"a", "b"}; // reuse of the array.
// more code.
for (Sring s : args) {
// what will this loop get"?
// The answer is: a, b
// but will you remember this fact in a month if "more code" above is 50 lines long?
}
}
Passing objects is essentially passing references. E.g., your array will only exist in one place in memory when passing it between functions. Here's a runnable example illustrating that.
If you like you can reuse the same array in your routine. Note that changes made to that array will be visible to all objects sharing the same reference to that array. If that's not desirable then you must declare a new array.
String parentArray = {"S","B","R"};
// no need to use new operator to hold subSetArray.
String subSetArray = returnSubSet(parent);
public String[] returnSubSet(String[] _parent)
{
return Arrays.copyOfRange(_parent,1,2);
}
, when I pass a variable like array to
a function does it creates a new space
for the array in the heap each time I
pass it as parameter to further
functions or just it uses the same
space in the heap & just passes the
reference?
Answer
1. Object in Java are Pass by reference by value
2. when you pass an array to a function , a _parent variable will be created in stack and it points to the same Array Object in heap.
UPDATES: Primitive example
int global_scope_variable=10;
setValue(global_scope_variable);
public void setValue(int val)
{
// val is visible only within this method.
System.out.println(val); // output is 10
val=20;
System.out.println(val); // output is 20
System.out.println(global_scope_variable); // output is 10
}