how does this work? - Java code - java

So I've got this piece of code,
package test1;
class Student13
{
public static void main(String [] args)
{
Student13 p = new Student13();
p.start();
}
void start()
{
long [] a1 = {3,4,5};
long [] a2 = fix(a1);
System.out.print(a1[0] + a1[1] + a1[2] + " ");
System.out.println(a2[0] + a2[1] + a2[2]);
}
long [] fix(long [] a3)
{
a3[1] = 7;
return a3;
}
}
Can you tell me why it returns 15 15 and not 12 15? Function fix is applied only for long[] a2, so how come that the final result is 15 15?

You pass the a1 array to fix(), which is called a3 in the fix() method, but is regardless still referencing a1. So when you update a3: a3[1]=7, you actually update the paramater value of fix() which was a1. Thus you updated a1!

In the line
long a1[] = { ... };
you are creating one array object. This will be the only one throughout the rest of the program.
Now the call to
fix(a1);
assigns a reference to exactly that array to the parameter a3 in this fix method. As this method returns this reference (return a3;), the line
long[] a2 = fix(a1);
will assign the same reference to the variable a2. So at all points, all variables and parameters referred to the same array.
The fix method is modifying that array. So the modification is seen by all aliases you have.

Reference of a1[] is passed as a parameter to fix() that's why basically
a1[] == a2[] after calling fix().
a2[] is pointing to a1[] but a1[] sum is now 15, so a2[] sum is also 15.

Related

Beginner Java methods [duplicate]

This question already has answers here:
Non-static variable cannot be referenced from a static context
(15 answers)
Closed 5 years ago.
public class Test {
int[] a1 = {1, 3, 5, 7, 2};
int[] a2 = new int[a1.length + 10];
public static int[] Array(){
for(int i = 0; i < a1.length; i++){
a2[i] = a1[i];
}
a1 = a2;
}
public static void main(String args[]){
System.out.println(a1.toString);
}
}
I am trying to create a method "Array" that will take in arrays a1 and a2 and add + 10 to the length of a1. My problem is that I don't know how to correctly name the method and how to call it in the main in order to print.
I have tried passing a1 and a2 in the constructor for Array but it doesn't work. I have also tried printing directly in the main() and it doesn't work either. What am I missing?
No idea what are you trying to do but in Java you can't change the size of array once it is declared but if you want to work with array with can change size then you should use arraylist not array and one more thing setting b = awould not work btw here is a code which swaps elements from one array to other but once again you can't change size of array in java: I return b back but you don't need to return an array back because an array variable(name of array) refers to a memory location.
public static int[] extendLength(int [] a, int [] b){
for(int i = 0; i < a.length; i++){
b[i] = a[i];
}
return b;
}
public static void main(String args[]){
int[] a1 = {1, 3, 5, 7, 2};
int[] a2 = new int[a1.length + 10];
int [] res = extendLength(a1,a2);
for(int i = 0; i < a2.length;i++)
System.out.println(a2[i]);
}
Long story short, the way you have your program set up, your variables will also need to be static; otherwise, your static methods will not be able to access them.
Static fields and methods are essentially singular to the class; therefore without a director to which object contains the field, asking a static method to manipulate a non-static field is very ambiguous.
I'm seeing a number of other problems in this program as well; namely, you're treating toString as a field (it's a method), your array method is missing a return statement, and your alignment is all over the place. This probably isn't an appropriate question to bring to Stack Overflow; I would encourage you to look at a tutorial, like the one at Tutorials Point, before bringing your question here.

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

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

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);

Call by reference or Call by value

Could somebody please explain how this program is executed?
Here is the code whose output I just can't quite seem to get it:
class Box {
int size;
Box (int s) {
size = s;
}
}
public class Laser {
public static void main(String[] args) {
Box b1 = new Box(5);
Box[] ba = go(b1, new Box(6));
ba[0] = b1;
for(Box b : ba)
System.out.println(b.size + " ");
}
static Box[] go (Box b1, Box b2) {
b1.size = 4;
Box[] ma = {b2, b1};
return ma;
}
}
The actual output when I run this is 4, 4. But according to my understanding this should be 5, 4.
Can anyone please help understand how this is being executed?
I have added the comments for you;
The important TWIST that you missed here is;
Box[] ma = {b2, b1}; its not {b1,b2}. Memory locations are interchanged while returning.
public static void main(String[] args) {
Box b1 = new Box(5); // b1 == location A
Box[] ba = go(b1, new Box(6)); // ba == location B which stores Location A, D
// PLEASE NOTE HERE
// After the function go() is executed;
// ba[] will have {D, A}
// So ba[0] will have object b1 which is at location A.
ba[0] = b1; // location B will now store A and A
for(Box b : ba)
System.out.println(b.size + " "); // Output: 4 and 4
}
static Box[] go (Box b1, Box b2) { // go(location A, location D )
b1.size = 4; // A's object.size = 4
Box[] ma = {b2, b1}; // position is interchanged here (D and A)
return ma; // return the location of ma
}
Hope this helps.
Do let me know if you have any questions. Everything is pass by value in java. The memory addresses are passed by value.
When you pass an object as a parameter, you're actually passing a copy of a reference to it. That is, if you modify the parameter object inside the method, the object will retain those modifications when that method returns, which is why you see b1 retaining the size = 4 assignment after go returns.
Java always passes references to objects in method calls. When you're calling go, the first argument (b1), is a reference to the same b1 Box that you have in your main. You then modify that object, whose size is now 4.
The values passed to go are references to the objects. If you're coming from C, you can think of the parameters as having pointer types, something like
Box** go (Box *b1, Box *b2) {
b1->size = 4;
/* allocate an array of Box*, set it up, return it */
}
(Sorry if I got the C syntax wrong.) The pointers (references) themselves are passed by value, which means that if you say inside "go" (in the C program):
b1 = &some_other_box;
it doesn't affect any variables on the calling side, and it works the same way in Java. This makes it a bit different than a var parameter in PHP or Pascal.
Java passes copies of references to objects in method calls.
You can't change an object by assigning to it.
public static void main(String[] args) {
Box b1 = new Box(5);
Change(b1);
System.out.println(b1.size + " ");
static void Change(Box b1) {
b1 = new Box(6);
}
This will always return 5, because the function Change only overwrites the copy to the referenced object.
You can however affect the object's properties like so:
public static void main(String[] args) {
Box b1 = new Box(5);
Change(b1);
System.out.println(b1.size + " ");
static void Change(Box b1) {
b1.size = 6;
}
This will return 6 (the reference to the object remains unchanged).
If the function 'go' in the original post is in C (and b1 and b2 are C pointers), it can do the following two things (which the caller will see):
Change the value of variables in the data structures pointed to by b1 and b2.
Make the original b1 and b2 point to different data structures.
In Java, we can do 1 but NOT 2, since go does not have access to the original b1 and b2. (It has access to copies of b1 and b2. At the beginning of the subroutine, the copy b1 points to the same object as the original b1 and so on.)
Saying Java is pass by call DOES miss something, namely the ability of the function to do 1, i.e., change the properties of the object in the heap referenced by b1 and b2. [This is what happens in the statement, b1.size = 4;, which caused the original poster's confusion.]
b1 in 'go' is NOT the same location as b1 in 'main'. However, when the function starts, b1 in 'go' references the same object as b1 in 'main' and any changes made to the object using b1 in 'go' will be seen when b1 in 'main' is used as the reference.
However, if b1 in 'go' is set to another Box, b1 in 'main' will NOT see this; it will still see the previous Box.
In Java, objects are passed by reference, primitives are passed by value.
public class Laser {
public static void main(String[] args) {
//Create a Box of size 5.
Box b1 = new Box(5);
//Create an array of Box objects, which are the results of the go method
Box[] ba = go(b1, new Box(6));
// ba now looks like {new Box(6), b1 /*b1 is size 4 now*/}
// assign reference to b1 at index 0 in ba.
ba[0] = b1;
// array now looks like {b1, b1}
for(Box b : ba)
System.out.println(b.size + " ");
}
static Box[] go (Box b1, Box b2) {
//set the size of the first box to 4
b1.size = 4;
//create an array of boxes, with b2 in index 0 and b1 in index 1
Box[] ma = {b2, b1};
return ma;
}
}

Java copying understanding

After testing the code (see below), I found out that I don't understand some fundamentals.
Class A.
class A {
private String s;
private int[] array;
private B b;
public A(String s, int[] array, B b) {
this.s = s;
this.array = array;
this.b = b;
}
}
Class B.
class B {
public int t;
public B(int t) {
this.t = t;
}
}
I thought that any changes I did after A a = new A(s, array, b); would affect a. Don't all the fields of a and the variables s, array, b refer to the same object?
String s = "Lorem";
int array[] = new int[] {
10, 20, 30
};
B b = new B(12);
A a = new A(s, array, b);
s = "Dolor";
array = new int[] {
23
};
b = new B(777); // Initialized with a new value, a.b keeps the old one. Why?
System.out.println(a);
The output.
String Lorem
Array [10, 20, 30]
B 12
And about this.
B b2 = new B(89);
B b3 = b2;
System.out.println(b3);
b2 = null;
System.out.println(b3); // b2 initialized with null, b3 keeps the old one. Why?
The output.
89
89
However, if I have two lists, this shows that they both refer to same object.
ArrayList<String> first = new ArrayList<String>();
first.add("Ipsum");
ArrayList<String> second = new ArrayList<String>();
second = first;
first.add("The Earth");
System.out.println(second);
The output.
[Ipsum, The Earth]
The difference is assignment versus modification.
Assignment (=) makes the variable point to something else, so this won't change the underlying data. So any other variables pointing to the same data don't change.
Modification (pretty much anything except =) doesn't change what the variable points to, it just modifies the underlying object. So any other variables pointing to the same data do change.
For you example:
b = new B(777); is assignment, so only b is changed to point to something else. a.b won't change.
b2 = null; is assignment, so only b2 is changed to point to something else. b3 won't change.
If you were to say b2.t = 5, this would be modification (we're not assigning a new value to b2, we're modifying it by changing one of its members), so b3 will change as well.
I hope that explains it.
No. The thing is, you are not changing a, you are assigning a new value to s. S is a String, which are immutable, which means you can never make a change to the value of s. You can, however, change the reference in S, which is what you are doing.
To make yourself more clear try these lines of code..
String s = "Lorem";
int array[] = new int[] {10, 20, 30};
B b = new B(12);
//A a = new A(s, array, b);
s = "Dolor";
array = new int[] {23};
b = new B(777);
A a = new A(s, array, b);
System.out.println(a);
ArrayList<String> first = new ArrayList<String>();
first.add("Ipsum");
ArrayList<String> second = new ArrayList<String>();
second = first;
second.add("The Earth");
first.remove("The Earth");
System.out.println("second :"+second);
What are the current values the String s, array and the object b are holding while creating the instance of class A ( at the time of calling class A constructor ) will be printed. After creating class A instance, the String s, array and object b will be referred as a.s, a.array and so. If you assign a new value to s, array and b, it wont affect the class A instance.
And for the array list question, the two array lists will refer the same reference only. If you want different reference then do like this... (But always = assign operator will make same reference only )
ArrayList<String> first = new ArrayList<String>();
first.add("Ipsum");
ArrayList<String> second = new ArrayList<String>(first);
second.add("The Earth");
System.out.println("first :"+first);
System.out.println("second :"+second);
Thanks Dukeling for explaing how assignments works with objects and primitives, I am adding here to explain how the list works when operations performed on them.
When we consider the two array lists created in the above code in the question, both the variables first and second are pointing to the same array object that resides in the memory.
So when an add operation is performed the underlying object itself gets updated. So the print operation prints the second array list which pointed to the same array-list object created during the creation of first array-list.

Categories