Shoud Java be considered as "Strictly pass by value"? [duplicate] - java

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 3 years ago.
In Pass By value when arguments are passed by value to a method, it means that a copy of the original variable is being sent to the method and not the original one, so any changes applied inside the method are actually affecting only the copy version and not the original one.
for example,
public class Test {
private void squareNumber(int number){
number=number*number;
}
public static void main(String[] args) {
int x=2;
System.out.println(x); //output = 2
new Test().squareNumber(x);
System.out.println(x);//output = 2
}
}
But in case of Arrays and List, this doesn't work like this and below is the example of ArrayList
public class Test {
private void squareOfList(List<Integer> integerList){
for (int i=0;i<integerList.size();i++) {
integerList.set(i,integerList.get(i)*integerList.get(i));
}
}
public static void main(String[] args) {
List<Integer> nums= new ArrayList<>();
nums.add(2);
nums.add(3);
nums.add(4);
nums.add(5);
System.out.println(nums); // output = [2, 3, 4, 5]
new Test().squareOfList(nums);
System.out.println(nums); // output = [4, 9, 16, 25]
}
}
Since we have passed nums as a parameter, only the value inside the method should change but it is changing the value of the original list.
Does this "STRICTLY Pass by value" term hold good?

int is primitive type and List is Reference type. According to JLS
The reference types are implemented by dynamically created objects that are either instances of classes or arrays. Many references to each object can exist.
When you pass a value of any reference type in a function only the reference is copied. Now both the references (caller, callee) are pointing to the same dynamically allocated memory. If you change that (dynamically allocated memory) in callee it is going to reflect in caller.
A variable of a primitive type holds a value of that exact primitive type
int is primitive type and it holds the value. when passed to a function it copies the value and there is no dynamically allocated memory which is shared. therefore all the changes you make in function remain in the function.
This example may clarify it further
public class Test {
private void squareOfList(List<Integer> integerList){
integerList = new ArrayList<>(); // Refering to a different dynamically allocated memory
}
public static void main(String[] args) {
List<Integer> nums= new ArrayList<>();
nums.add(2);
System.out.println(nums); // output = [2]
new Test().squareOfList(nums);
System.out.println(nums); // output = [2]
}
}
For further information read chapter 4 of java language specification.

Related

Why is the following Output the right one? [duplicate]

This question already has answers here:
Assigning Array to new variable, changing original changes the new one
(4 answers)
Problem with assigning an array to other array in Java
(4 answers)
How can an integer array be a reference type?
(2 answers)
Closed last month.
public class Alle {
public static void main(String[] args) {
int[] arr = {1,2,3,4};
int [] y = arr;
y[0] = 15;
System.out.println(Arrays.toString(arr));
}
}
The Output is 15,2,3,4 but why? I never changed "arr".
In Java, arrays are objects, not primitive types. When you are assigning link to arr to the new variable, y still points to arr, so you are actually changing arr. Thats it. But if you want to copy the array, you can use this method: Arrays.copyOf(int[] original, int newLength)
Let's assume you have a son, named jackson.
You introduce him to your friend, "Hey Friend, meet my son Jackson".
The friend says, "Hi Jackson, I'll call you jake."
Later that friend calls him and says, "Hey Jake, here take a handful of candies".
your son Jackson comes to you, and you see he has a handful of candies.
But how ? You never gave jackson candies. But your friend gave to jake.
Makes sense ?
In your code, the arr, and the y are exactly the same entity, not equal, not copy, but the exact same Object. So you make changes at one place, it'll show at the other one as well.
When you initialized the integer array viz arr in your case, it allocated a space in the heap to your reference variable arr when you executed the following code:
int[] arr = {1,2,3,4};
This arr is referring to an integer array in heap as arrays are objects in java.
Now when you performed the following code:
int [] y = arr;
This created one more reference variable y which is referring to the same object in the heap that your reference variable arr was referring to, that is why whatever changes you make through your reference variable y or reference variable arr will reflect the changes of the object created in the heap as they are referring to the same object.
If you want a new object allocated to your reference variable y that resembles the elements of your arr array then you can clone it. The following code represents it:
public class Alle {
public static void main(String[] args) {
int[] arr = {1,2,3,4};
int [] y = arr.clone(); //change here
y[0] = 15;
System.out.println(Arrays.toString(arr));
}
}
This gives an output:
[1, 2, 3, 4]
Hence your arr array is not affected this time.

I don't understand how Java is pass by value [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 7 years ago.
So I thought Java was pass by value but why does the following code:
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<Integer>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
phase1(numbers);
for (Integer number: numbers) {
System.out.println("number = " + number);
}
}
static void phase1(List<Integer> numbers) {
numbers.remove(0);
}
Print the following?
number = 2
number = 3
So I thought Java was pass by value
It is.
...but why does the following code...print the following?
Because the value passed for reference types is the reference, not a copy of the object.
"Pass by reference" refers to a completely different thing, passing a reference to the variable. Java doesn't have that.
If Java had pass-by-reference, then this change to your method:
static void phase1(List<Integer> &numbers) {
// Pass-by-reference indicator --^--- that Java doesn't actually have
numbers = new ArrayList<Integer>()
}
...would make your code print no numbers at all. But it doesn't, so it doesn't.
Think of the object reference as an int or long that uniquely identifies the object elsewhere in memory. (Which is basically what it is.) Just as a = b with ints copies b's value into a, so a = b copies b's value into a even when the value is an object reference. The value being copied is the reference, not the object it refers to.

Arrays and Referencing [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
Consider the following code:
public static void resize(int[] x){
x = new int[x.length*2];
System.out.println(x.length + " ");
}
public static void main(String[] args){
int[] x = {1,2};
resize(x);
System.out.println(x.length);
}
The output is "4 2". The question is: I thought that when we are defining an array in the code of the new length, the other array (the previous one with length 2) would be discarded, as now the value of the array points to the "larger" array. So, why would then print out at the end as length 2? I used Arrays.toString to verify, and indeed, the actual values of the array after the void method are {1,2}. This is confusing, as I thought that the array itself would be changed as the value is a pointer to the memory address (in contrast with using the method on a char/int variable, which would not affect the value of the variable).
When you call resize, you pass an array object to the method. This is the basic flow of your program:
initialize array of size 2
pass that array to resize()
resize has a reference to the value of the array
resize points it's reference to a new array twice the size of the old reference
prints "4"
main() prints the size of the initial array "2"
You don't change the original array in the new method, it merely has an array of the same value.
Because Java passes by value, the array doesn't change after your call to resize. (I'm assuming the output is actually 4 2, not 2 4.)
If you want resize to effect a permanent change, you should have the method return x; as its final statement (or use a global variable):
public static int[] resize(int[] x){
x = new int[x.length*2];
System.out.println(x.length + " ");
return x;
}
public static void main(String[] args){
int[] x = {1,2};
x = resize(x);
System.out.println(x.length);
}
The scope of your x variable in resize
public static void resize(int[] x){
x = new int[x.length*2];
}
is local to that function. It does not affect the x that was passed in. This means that as soon as resize completes, that local copy disappears and is eventually garbage collected.
If you want to resize the original array, return it. For example:
public static int[] getNewArrayOfDoubleLength(int orig_length){
return new int[orig_length * 2];
}
And call it with
x = getNewArrayOfDoubleLength(x.length);
Since arrays are immutable, this is a new array. The original one still exists (although it's inaccessible) until it's garbage collected.

Is Java pass by value Or pass by reference Or both? [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 9 years ago.
Consider following case.
List<Integer> listOne = new ArrayList<>();
List<Integer> listTwo = new ArrayList<>();
listOne.add(1);I think this happens due to
listOne.add(2);
listOne.add(3);
Collections.reverse(listOne);
listTwo = listOne; //listTwo has same reference
Collections.reverse(listOne);
System.out.println(listOne); //out put [1, 2, 3]
System.out.println(listTwo); // same out put
Java is pass by value, where values (for non primitive types) happen to be references. I think this provide survival for java for this kind of scenario. To be honest why java try to avoid pass by reference and try to be different from some of other languages? while java still suffering from pass by reference behaviors?
Edit: additionally please some one explain what happen in above code
Java does not suffer from pass by reference behaviors, it enjois them :)
when you write
List listOne = new ArrayList<>();
you have three things to consider:
1) a variable, which is a chunk of memory, and is named listOne
2) an object on the heap, with is an instance of ArrayList, which is a larger chunk of memory, and has no name
3) value of the listOne variable, which is not a memory chunk, but is a set of 0s and 1s placed in the memory of the variable listOne, and that value also has no name.
Now when we talk if listOne is passed by value or by reference, we use imprecise jargon which leads to misunderstanding. listOne (thing 1) is not passed at all, neither by value nor by reference. The value of listOne (thing 3) is passed, and this gives access to the ArrayList object (thing 2). So if we use name "listOne" but mean thing 3, it is passed by value, and if we mean thing 2, it is passed by reference. In both cases, name "listOne" is not correct name for thing 2 or thing 3, but it is used because it is short and convenient.
Java is pass by value.A copy of actual argument is passed to parameters.It is evident in case of primitive data types where changes in formal parameters is not shown in actual arguments.
static void incre(int a)
{
a++;
}
public static void main (String a[])
{
int c=3;
incre(c);
System.out.println(c); //still prints 3
}
Exact thing happens in case of references, but making a copy of reference does not create a new object, they both point to same object now.Hence changes made by references is reflected here.
class Demo {
int c =2;
Demo(int c)
{
this.c=c;
}
void incObject (Demo x)
{
(x.c)++;
}
int show()
{
return c;
}
public static void main (String []args)
{
Demo o = new Demo(1);
o.incObject(o);
System.out.print(o.show()); //prints 2
}
}
Collections.reverse();
modifies the backing array. This is clear from the implementation:
public static void reverse(List<?> list) {
int size = list.size();
if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {
for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--)
swap(list, i, j);
} else {
ListIterator fwd = list.listIterator();
ListIterator rev = list.listIterator(size);
for (int i=0, mid=list.size()>>1; i<mid; i++) {
Object tmp = fwd.next();
fwd.set(rev.previous());
rev.set(tmp);
}
}
}
Now, listOne and listTwo have the same reference which points to the same backing array. So, no matter which handle(listOne or listTwo) modifies the backing array, the other will reflect the same changes. In your case:
Collections.reverse(listOne); // backing array has [3,2,1]
listTwo = listOne; //listTwo has same reference
Collections.reverse(listOne); // backing array has [1,2,3]
System.out.println(listOne); //out put [1, 2, 3]
System.out.println(listTwo); // same out put
As far as pass by value/reference is concerned. You said it yourself:
Java is pass by value, where values happen to be references.
why java try to avoid pass by reference and try to be different from
some of other languages?
One of the main reasons would be that Java(JVM) manages its own memory.
Collections.reverse(listOne); passes the reference to listOne(the object) by value, which is how one defines "pass by reference". Everything other than primitives is passed this way: by reference. It does not try to avoid it, it is only different from C++ in that it doesn't explicitly use pointers.
EDIT: Okay, I think I see where you're coming from.
private static void changelist(List<Integer> list) {
list.add(4);//This modifies the list object
list = new ArrayList<Integer>();//This modifies the local copy of the reference to the list object
list.add(5);
}
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
System.out.println(list);//output is [1,2,3]
//This copies the value of the reference.
//If you modify the object in the underlying
//function, changes will be preserved when you return
//However if you modify what the reference points to,
//the function will only modify the local copy
changelist(list);
System.out.println(list);//output is [1,2,3,4]
}

Array and methods?

I'm doing a task for a course in Java programming and I'm not sure how the following thing is working? The method below takes the value from an array and a integer. The integer should be added to the array and then be used outside the method in other methods and so on, but how could this work when the method has no return for the new content of the array? There is a void in the method? Have I missed something? Preciate some help? Is there something about pointers?
public static void makeTransaction(int[] trans, int amount);
Arrays in Java are objects. If you modify the trans array inside the method, the changes will be reflected outside of it1. Eg:
public static void modify(int[] arr)
{
arr[0] = 10;
}
public static void main(...)
{
int x = {1, 2, 3};
System.out.println(x[0]); // prints 1
modify(x);
System.out.println(x[0]); // now it prints 10
}
Note that native arrays can't be dynamically resized in Java. You will have to use something like ArrayList if you need to do that. Alternatively you can change the return type to int[] and return a new array with the new element "appended" to the old array:
public static int[] makeTransaction(int[] trans, int amount)
{
int[] new_trans = Arrays.copyOf(trans, trans.length + 1);
new_trans[trans.length] = amount;
return new_trans;
}
1 It is also worth noting that as objects, array references are passed by value, so the following code has no effect whatsoever outside of the method:
public void no_change(int[] arr)
{
arr = new int[arr.length];
}
You can't add anything to an array. Java arrays have a fixed length. So indeed, what you want to do is impossible. You might make the method return an int[] array, but it would be a whole new array, containing all the elements of the initial one + the amount passed as argument.
If you want to add something to an array-like structure, use an ArrayList<Integer>.
Do you have to keep the method signature as is?
Also, can you be a bit more specific. When you say "the integer should be added to the array", are you referring to the amount argument? If so, then how is that amount added? Do we place it somewhere in the array or is it placed at the end, thus extending the array's length?
As far as pointers go, Java's pointers are implicit, so if you don't have a strong enough knowledge of the language, then it might not be so clear to you. Anyways, I believe that Java methods usually will pass objects by reference, and primitives by value. But, even that isn't entirely true. If you were to assign your object argument to new object, when the method terminates, the variable that you passed to the method is the same after the method executed as it was before. But, if you were to change the argument's member attributes, then when the method terminated those attributes values will be the same as they were inside of the method.
Anyways, back to your question, I believe that will work because an array is an object. So, if you were to do the following:
public static void makeTransaction(int[] trans, int amount)
{
trans[0] = amount;
}
// static int i;
/**
* #param args
*/
public static void main(String[] args)
{
int[] trans = {0,1,3};
makeTransaction(trans, 10);
for(int i = 0; i<trans.length; i++)
{
System.out.println(trans[i]);
}
}
The output of the array will be:
10
1
3
But, watch this. What if I decided to implement makeTransaction like so:
public static void makeTransaction(int[] trans, int amount)
{
trans[0] = amount;
trans = new int[3];
}
What do you think that the output will be? Will it be set to all zero's or will be the same as it was before? The answer is that the output will be the same as it was before. This ties in to what I was saying earlier.
I might've assigned that pointer to a new object in memory, but your copy of the pointer inside of the main method remains the same. It still points to the same place in memory as it did before. When the makeTransaction method terminates, the new int[3] object that I created inside of it is available for garbage collection. The original array remains intact. So, when people say that Java passes objects by reference, it's really more like passing objects' references by value.

Categories