Local variable behaviour with list, string, and stringbuffer [duplicate] - java

This question already has answers here:
Why is an ArrayList parameter modified, but not a String parameter? [duplicate]
(5 answers)
Closed 5 years ago.
I am a newbee.
I have read that the scope of local variables will be within a block (correct me if I am wrong).
Here, the main method's local variables (the lists li and li1, and the StringBuffer y) are behaving like instance variables, and the variables (String y1 and int x) behave like local variables. Why ?
public class Test {
public static void addValues(ArrayList<String> list, StringBuffer sb, int x){
list.add("3");
list.add("4");
list.add("5");
sb.append("String Buffer Appended !");
x=x+10;
}
public static void addValues(ArrayList<String> list, String sb, int x){
list.add("3");
list.add("4");
list.add("5");
sb = sb + "is Appended !";
x=x+10;
}
public static void main(String[] args) {
ArrayList<String> li = new ArrayList<>();
ArrayList<String> li1 = new ArrayList<>();
StringBuffer y=new StringBuffer("ab");
int x=10;
String y1=new String("ab");
li.add("1");
li.add("2");
li1.add("1");
li1.add("2");
System.out.println("b4 : "+li+" , y = "+y+" , y1 = "+y1+" x= "+x);
addValues(li,y,x);
System.out.println("Af : "+li+" , y = "+y+" x= "+x);
addValues(li1,y1,x);
System.out.println("Af : "+li1+" , y1 = "+y1+" x= "+x);
}
}
Output :
b4 : [1, 2] , y = ab , y1 = ab x= 10
Af : [1, 2, 3, 4, 5] , y = abString Buffer Appended ! x= 10
Af : [1, 2, 3, 4, 5] , y1 = ab x= 10

In the case of the ArrayList and StringBuffer, you are passing a reference to an mutable object which reflects any modification on any variable that holds the same reference.
In the case of the String you are too passing a reference BUT its immutable so when you concatenate something to it, its actually creating a new String object and assigning a new reference to the variable within the method, you are not actually modifying the object itself.
And in the case of the int, all primitives are assigned and passed by value, so its actually making a copy of its value and passing it to the method, so anything you do to the variable within the method doesnt affect the variable outside of it.

Java always pass by value, means it will always pass the copy of the variables (primitive variable and reference variable) to the method's block of code.
When we pass an Object reference variables (in this case ArrayList and StringBuffer), actually we are copying the bit pattern of there reference variable, not the real object it self, the new copy in your addValues method refer to EXACTLY the same object as the the one declared in main method, so whenever we modify the value of the object's member the copy and actuall object reference variable will see the changes.
the String by default are immutable and int, they by default are immutable. so whenever we pass them to the methods as a paramater, the methods will only have the copy of the value from the String and int.
Your question related to "Stack and Heap" in java . you could watch this video as a reference

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.

One dimensional array in Java

When I run this code on cmd prompt with statement :
java Test A
output is
a
b
c
Wasn't it suppose to result in an error since dimension of args is 1 whereas dimension of x is 3 (args=x).
class Test
{
public static void main(String args[])
{
String[] x={"a","b","c"};
args=x;
for(String i: x)
{
System.out.println(i);
}
}
}
well, the array variable in java is only a reference, so if you give it another reference for a String array it will accept it, so the range of values the array variable(args) accepts is the references to String arrays at memory, it's like changing the value of an integer from 1 to 3, it's ok because they're both valid, and in the range that the integer accepts.
It will not result in an error because your object is not final and you are not changing the array object.
here
double[] data = new double[5]{2, 4, 5, 6, 8} // data can change but the instance of the class cant change
double[] data = new double[7] // here you are changing the data but not the object i.e the created instance of the object does not change but the instance the data(the variable) is holding changes
I hope you got your answer

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.

why identifier of a wrapper class object does not work as a reference variable

My question involves wrapper classes. I know that when we store a primitive type literal by using wrapper classes, we are storing it as a object of that wrapper class so object's identifier will be a reference variable (somehow like a pointer in c++). For instance, in Integer wi = new Integer("56"), wi is a reference variable. But if that is true:
Why can I do wi++ or wi +=2? Why does compiler deal with those reference variables like normal primitive variables? Doesn't a reference variable store reference of a object?
Given Integer wi = new Integer("56") and int pi = 56, why does (wi == pi) returns true. Isn't wi supposed to store a reference (address)?
And another question: When a reference variable is passed to a method as parameter it counts as passing by reference so the modifiction that happens
to that reference variable should affect it's value but it doesn't:
public class Main {
void show(Integer x){
x *=100 ;
}
void goo(int x){
x *=100 ;
}
public static void main(String[] args) {
Main mn = new Main() ;
Integer wi = new Integer("86");
int pi = 86 ;
mn.goo(pi);
System.out.println(pi); //output = 86
mn.show(wi);
System.out.println(wi); //output = 86, shouldn't it be 8600?
}
}
the statement mn.goo(pi) passes the copy of value 86 while mn.show(wi) passes the copy of reference variable which holds the same object.
why can i do this? wi++ or wi +=2 .i mean why does compiler deal with those reference vriables like normal primitve variables?(doesn't a reference variable store reference of a object?)
Because of the concept of autoboxing and auto-unboxing, wi is converted to primitive, incremented, then then converted back to Wrapper
2.or if we have==>" Integer wi = new Integer("56") " and "int pi = 56" . why does (wi == pi) returns true. isn't wi supposed to store refernce (address)
This is because for Integer wrapper classes, the == will return true for the value till 128. This is by design
For your doubts regarding passign primitives and object references, Please study these programs
class PassPrimitiveToMethod
{
public static void main(String [] args)
{
int a = 5;
System.out.println("Before Passing value to modify() a = " + a);
PassPrimitiveToMethod p = new PassPrimitiveToMethod();
p.modify(a);
System.out.println("After passing value to modify() a = " + a);
// the output is still the same because the copy of the value is passed to the method and not the copy of the bits like in refrence variables
// hence unlike the reference variables the value remains unchanged after coming back to the main method
}
void modify(int b)
{
b = b + 1;
System.out.println("Modified number b = " + b);
// here the value passed is the copy of variable a
// and only the copy is modified here not the variable
}
}
The output is
Before Passing value to modify() a = 5
Modified number b = 6
After passing value to modify() a = 5
Passing object reference to method
class PassReferenceToMethod
{
public static void main(String [] args)
{
Dimension d = new Dimension(5,10);
PassReferenceToMethod p = new PassReferenceToMethod();
System.out.println("Before passing the reference d.height = " + d.height);
p.modify(d); // pass the d reference variable
System.out.println("After passing the reference d.height = " + d.height);
// the value changes because we are passing the refrence only which points to the single and same object
// hence the values of the object are modified
}
void modify(Dimension dim)
{
dim.height = dim.height + 1;
}
}
The output is
class PassReferenceToMethod
{
public static void main(String [] args)
{
Dimension d = new Dimension(5,10);
PassReferenceToMethod p = new PassReferenceToMethod();
System.out.println("Before passing the reference d.height = " + d.height);
p.modify(d); // pass the d reference variable
System.out.println("After passing the reference d.height = " + d.height);
// the value changes because we are passing the refrence only which points to the single and same object
// hence the values of the object are modified
}
void modify(Dimension dim)
{
dim.height = dim.height + 1;
}
}
The output is
Before passing the reference d.height = 10
After passing the reference d.height = 11
The java compiler automatically inserts intValue and Integer.valueOf calls to convert between int and Integer. For example, here's a code snippet from the question:
void show(Integer x){
x *=100 ;
}
And here is what really happens:
void show(Integer x) {
int unboxed = x.intValue();
unboxed *= 100;
}
As you can see, the line x *= 100 does not really change the Integer object you pass in, it only changes the int value extracted from that Integer object.
In a similar way, the code wi == pi from the question actually means wi.intValue() == pi, which explains your observation.
Java uses the "call by value" concept as described in detail here
So in your case x *=100 ; in method show only updates the local variable
Compiler unboxes wi to primitive data type.So now, it is a primitive data type,since everything in Java is pass by value, changes in the formal arguments will not affect actual arguements.
mn.show(wi);

Only array is being modified

This is the code I have, please look at it before you read the question
package ict201jansem2012;
public class Qn3b {
public static void main(String[] args) {
int a = 1;
int b[] = {4,5};
String s = "Good luck!";
method1(b[1]);
System.out.println("(1) b[0] = "+b[0]+"; b[1] = "+b[1]);
method2(b);
System.out.println("(2) b[0] = "+b[0]+"; b[1] = "+b[1]);
method3(a);
System.out.println("(3) a = " + a );
method4(s);
System.out.println("(4) s = " + s );
}
public static void method1(int b) {
b = 7;
}
public static void method2(int[] b) {
b[0] = 3;
}
public static void method3(int a) {
a = 3;
}
public static void method4(String s) {
s = "UniSIM";
}
}
Output:
(1) b[0] = 4; b[1] = 5
(2) b[0] = 3; b[1] = 5
(3) a = 1
(4) s = Good luck!
So my question is ,
This is intresting for me to know as learning programmer. The int b array 0 index value has changed, but not the other variables like the String s and int a. Before i ran this program I roughly thought in my mind that the variable will change their values as the methods are called ,this is because the method is being called and the main method vairable such as a,s and b array are passed and then they are being modified.
So in a nutshell why is that the b array 0 index is changed while the other variables are not changed?
Because you said you were a beginner programmer, I'll do a little writeup to explain (or try to explain) exactly what is happening.
It is because you are passing an argument to your method1 - method4 methods
These arguments, themselves, are references to other objects.
When you use the assignment operator, an equals sign, you overwrite that reference for the value in the current scope - where variables can be 'seen'.
In your code:
In the case of method1 you are creating a new reference, the variable can only be seen within that scope. That is, when you then go b = << expr >> you are assigning the variable b within method1's scope the value, not b in the main scope. The same is true of your method3 and method4 methods, you are assigning a new value to the respective variables within that scope, as you are creating new references rather than altering the original objects.
But, method2's code behaves differently, this is because you are mutating the object inside that code. You are altering the object directly - rather than creating a new reference inside that scope.
Consider the code below
int[] array = new int[] {1, 2};
public void test()
{
method1(array);
System.out.println(array[0] + ", " + array[1]);
method2(array);
System.out.println(array[0] + ", " + array[1]);
}
// because we are working with objects, the identifier, can be different to the arrays identifier
// in this case, I've chosen to use 'a' instead of 'array' to show this
public void method1(int[] a)
{
// this mutates the array object
a[0] = 2;
}
public void method2(int[] array)
{
// this overwrites the method2.array but not the global array
array = new int[] { 1, 2, 3 };
}
We create a new array, with identifer 'array' in the global scope. (In Java, this would be the classes own scope)
In method1, we take an argument, which is the same object being passed as the global array object, so when we mutate it, both objects will change. So, the first print statement will be
"2, 2"
Where array[0] has been altered
N.B. Because we dealing with objects, the 'name' of the variable doesn't matter - it will still be a reference to the same object
However, in method2, we take an argument, like in method1, but this time we use the assignment operator to assign that variable to a new value in the scope that it's currently in - so the global array isn't altered, so we still print out
"2, 2"
For a beginner programmer, I would personally write a few test programs where you get to fully understand how variables and scopes work.
But just know, everytime you create a new block of code, a new scope is created, local variables to that scope can only be seen in that scope and ones below it.
For instance:
public void test()
{
int a = 5;
method1(a);
System.out.println(a); // prints 5
}
public void method1(int a)
{
// a is only viewable in the method1 scope
// and any scopes below it, that is, any scopes created within method1
// and since we use an assignment operator, we assign method1.a a value, not global 'a' a value
a = 123;
if (true)
{
// this is a new scope, variables created in this block cannot be seen outside it
// but can see variables from above it
System.out.println(a); // prints 123
}
}
Here, we create a new scope inside method1 inside the if statement, which can see a above it. However, because method1 and test's scopes are both independent, when we use the assignment operator, we assign the value of a to the local scope. So a is different in both test and method1
I hope you understand better now.
I'm not very good at conveying things, but if it even helped a little bit in understanding scopes I did well, plus, it was fun.
Java is pass-by-value, but most values (everything that's not a primitive, in this case int[] and String) are references, which means they act like pass-by-reference.
Here's a nice writeup: http://javadude.com/articles/passbyvalue.htm
arrays are special type of objects and memory will be allocated on HEAP. When you pass array as parameter to method it will be pass as reference-value (copy of the reference).
This means initial b and this new reference points to same object. Unless new reference points to another object, changes on this reference will reflect on same object. That is why you are seeing value reflected on original array.
All of the values were passed TO the inner methods, but the inner methods returned nothing. However, method2 modified the internal value of the array that was passed to it, so that inner value appeared modified on return.
Note that method2 is the only one where you did not assign to the variable (parameter) itself, but rather assigned to an element of the object whose reference was passed in.
There is a critical difference between modifying the reference (pointer) to an object, and modifying the object itself.

Categories