Java pass by reference and compiler optimization - java

In the function fermatFactorization(), a and b are being passed as reference parameters, since I am using the Long Class. However, in function testFermatFactorization() when I pass a and b to fermatFactorization(), the values of a and b do not get changed, and so testFermatFactorization() prints (0)(0). I tested this by printing out a and b in fermatFactorization(), and I got the output that I expected.
What am I overlooking? Could the compiler alter a and b in fermatFactorization() since they are only being assigned to?(doubtful)
public static void fermatFactorization(Long n, Long a, Long b)
//PRE: n is the integer to be factored
//POST: a and b will be the factors of n
{
Long v = 1L;
Long x = ((Double)Math.ceil(Math.sqrt(n))).longValue();
//System.out.println("x: " + x);
Long u = 2*x + 1;
Long r = x*x - n;
while(r != 0) //we are looking for the condition x^2 - y^2 - n to be zero
{
while(r>0)
{
r = r - v; //update our condition
v = v + 2; //v keeps track of (y+1)^2 - y^2 = 2y+1, increase the "y"
}
while(r<0)
{
r = r + u;
u = u + 2; //keeps track of (x+1)^2 - x^2 = 2x+1, increases the "x"
}
}
a = (u + v - 2)/2; //remember what u and v equal; --> (2x+1 + 2y+1 - 2)/2 = x+y
b = (u - v)/2; // --> (2x+1 -(2y+1))/2 = x-y
}
public static void testFermatFactorization(Long number)
{
Long a = 0L;
Long b = 0L;
fermatFactorization(number, a, b);
System.out.printf("Fermat Factorization(%d) = (%d)(%d)\n", number, a, b);
}

Java is pass by value. If you assign a new value to the argument, it won't affect the value in the caller method.
You have two options:
make your method return a and b - either in a int[] or using a separate FactorizationRezult class that has two fields. That way you will declare a and b as local variables in your called method, rather than taking them as parameters. This is the most advisable approach.
An alternative approach is to use a MutableLong and use a setValue(..) method - that way the changes will affect the object in the caller method. This is less advisable

a and b are references, not 'reference parameters', and they are passed by value. The values are changed in the called method but that has no effect on the caller.
There is no 'pass by reference' in Java.

In Java, everything is passed by value. There is no call-by-reference. Even when you pass an Object, it's reference is passed by value. So, when you pass a Long object, you are simply passing the reference to it by value.
Long, just like other primitive type wrappers, is "immutable". You can't change the long value it has inside. So, if you don't want to change your design, you have to make a mutable wrapper for long yourself (or use MutableLong) and pass it on. Changing your design to return the results instead of changing the method arguments is a much better way if you ask me.

Using the = operator clears out the spot in the memory where the local variable is stored and replaces it. This will not affect the original variable. Pass by value only allows you to modify data in in object (like modifying a field in it), not it's actual reference.

Related

Do wrapper class objects get unboxed while being assigned to another object?

When we assign objects of the same type to one another, the new object stores the address of the object that's being assigned to it. For instance, if I have my own class named CLA then the following code will produce 11 as the output:
public class CLA{
int val;
public static void main(String...args){
CLA ob1 = new CLA();
ob1.val = 10;
CLA ob2 = ob1;
ob1.val++;
System.out.printf("%d", ob2.val);
}
}
because ob2 would refer to ob1 and consequently show ob1's val.
However, the same doesn't happen for Wrapper classes. When I assign an Integer object to another, the operation simply behaves like we're dealing with values and not objects. As opposed to the above code, the output of the below code is 10:
Integer x = 10; //auto-boxed as new Integer(10)
Integer y = x;
x++;
System.out.printf("%d", y.intValue());
Why does this happen?
Do wrapper class objects get unboxed while being assigned to another object, so as to pass the value instead of the address??
When you do x++, it is the same as x = x + 1 so it is actually a new instance of Integer assigned to x but y still points to the old instance which value is 10.
Keep in mind that wrapper instances are immutable.
For an Integer x, the expression x++ can be understood like x = new Integer(x.intValue() + 1);. Its not exactly the same, but helps for understanding.
So, it doesn't modify the Integer object with the value 10 that x pointed to before the x++, it creates a new Integer object with the value 11 independent of the original 10 Integer, and assigns this 11 Integer to x.
But there's nothing in the x++ expression that would make y point to a different Integer instance. So y still points to the original 10.
That's the difference to the CLA example where you don't introduce a new instance with ob1.val++, but modify the single instance. If the Integer class had a public field value, then x.value++ would show the behaviour you expected - but the value field is (for good reason) private - not accessible to the outside.

Why there is need of return statement

I have very silly doubt that why we use return statement in method . Without using return statement in method we can also get required value
as example
package testing;
public class ReturnMethod {
static int a = 10;
static int b = 5;
static int c;
static int d;
public static void add() {
c = a + b;
}
public static int returnAddValue() {
d = a + b;
return d;
}
public static void main(String[] args) {
add();
System.out.println("c: " + c);
int value = returnAddValue();
System.out.println("value: " + value);
}
}
In above example in both the cases i am getting output
c: 15
value: 15
So i am having doubt when to use return statement and why is neccessary
With return statement, the return value is not necessary to be saved in any global, external or member variable.
However, without return statement you have to prepare kind of outer variable value to track that.
If you assign the result of a method to a static variable (and, indeed, pass in the "parameters" of the method by setting static variables), you have problems when that method is called by two threads concurrently, since the variables are shared for all invocations of the method:
Thread t1 = new Thread(() -> {a = 1; b = 2; add(); }); t1.start();
Thread t2 = new Thread(() -> {a = 3; b = 4; add(); }); t2.start();
t1.join(); t2.join();
You don't know which of these threads run first, or even if they run at the same time; so you don't know what the value of a or b is when you call add(), and nor do you know whether the value in c afterwards is the result of the invocation in the first or second thread (or a mixture of the two).
The value stored in c afterwards could be any of 3, 5 or 7 (or any other value, if there is another thread which is also invoking add() concurrently outside this code.
This problem of thread interference just completely goes away if you keep values localized to the stack, by passing a and b as method parameters, and receiving the result as a return value.
Even if your code is single-threaded, it's simply ugly to have to write:
a = 1;
b = 2;
add();
int result = c;
rather than
int result = add(1, 2);
You should use a return statement, when you need the method to return a value.
In your case, both methods work.
But you can, and should use returning methods, when you don't want a field of your class to be changed by another class.
For example, you want money to be only seen, and not changed, when you are making a bank-account related software. So, you make money private, and make a method which returns the money. In this way, other classes can only see money, but not change it.
First, your functions are different, as you see
public static **void** add()
public static **int** returnAddValue()
First one does not return anything, because it has void as return type and the second one has int as return type.
First one works, because c is a global variable.
You typically would use return when you don't store the result in a (static) variable of your class.
public class ReturnMethod {
static int a = 10;
static int b = 5;
public static void add() {
int c = a + b;
}
public static int returnAddValue() {
int d = a + b;
return d;
}
public static void main(String[] args) {
add();
//not possible to access c here
//System.out.println("c: " + c);
int value = returnAddValue();
System.out.println("value: " + value);
}
}
In that modified example, there would be no way for you to access the result of the add() method.
You should probably read about Scopes in Java.
You have a class variable c & d. These variables are associated with the class and stored in heap. If you assign a value back to it and you can access it without a explicit return statement. But if you have declared d inside the method then return statement is required to give the value back to the caller.
The reason that you are able to access the value of class variable c is that it has been initialized as static. Had this not been the case the information in the c variable would be lost as soon as the add method ends. The reason methods have return value is that they user can get the updated value , if there are any manipulation in the object data. In this case there is a very small, what if there is series of manipulation with the data. In that case the final value has to be returned to the calling object which without return statement is not possible.
Its totally depends upon our requirement whether to return a value from our method or update instance variable. Some time we just want to process a value and get back the result in and result will be used in different manner, in this case we need to return value from method.
For example
java.lang.Math.sqrt(double a) method return a value and we use returned value as per our need OR requirement. Can you think if this method does not returned any value then what it should update, I think this method useless if it does not returned any value.
The variable C in your code snippet is accessed in the class throughout, and will stay until the object of the class exists. So you can print the value of Variable C outside the method.
However, if you had declared a local variable in the method add(), then print statement System.out.println("c: " + c); will print the default value for variable c. That is zero in this case.

Parameters passing in Java

I have a Long object in a class, I give it a value and then I pass it to another class' constructor, where it is changed. Why are the changes NOT visible in the first object?
The code:
public class ClassA {
private Long t;
public ClassA() {
t = new Long(10);
System.out.println(t); // prints 10
new ClassB(t); // it is modified (see ClassB)
System.out.println(t); // prints 10 again
}
public static void main(String[] args) {
new ClassA();
}
}
class ClassB {
private Long p;
public ClassB(Long p) {
this.p = p;
this.p = this.p + 1;
System.out.println(this.p); // prints 11
}
}
The output is: 10 11 10
The Long variable is initialized in ClassA. Then I pass it to ClassB, modify it and clearly the changes are not visible in the first class. Why?
It is because the Long class is immutable; once an instance is created, it can never change.
In this line:
this.p = this.p + 1;
what you are doing is create a new Long object. Other examples of immutable classes include all "wrapper" classes for primitive numeric types (Byte, Short etc) and String.
What doesn't help is that it makes the + operator unintuitive; what really does not help is that the language allows + on all of these immutable classes.
What happens in the above line could be written as (although it happens differently in the bytecode, I suspect):
long tmp = this.p.longValue();
tmp += 1;
this.p = new Long(tmp);
You can also verify immutability by marking your p as final in class B, which means the reference p can never change; this.p = this.p + 1 will raise a compile error since you attempt to modify reference p.
this line this.p = this.p + 1; does not modify p, it creates a new Long from adding the two values p and 1 and then sets this.p to be a reference to this new Long. Objects of the class Long do not have mutator methods so they can never change (within Class B this.p was not changed, this.p became a reference to a new Long)
So the behaviour is actually
this.p=p;
Long newLong=this.p + 1;
this.p=newLong;
What you're imagining is
this.p=p
this.p.imaginaryAddLocal(1);
this would effect the original p, but of course this method imaginaryAllLocal doesn't exist because objects of the class Long are immutable
To begin with, Long is immutable. It means you cannot change the value that you set in the constructor (note the absence of set methods).
When you do
this.p = this.p + 1;
Java does.
1) Autoconvert this.pto its long value (primitive)
2) Arithmetic operation
3) Autoconvert the result back to a new, different Long and assign the reference to this.p
t continues pointing, all the time, to the original Long object.
In Java, you modify objects through its attributes (not adviceable, you should make them private) or its methods. A + (or other operator) will never change an object state (although it may create a new one, in the only case of myString1 + myString2)
1- You are just modifying the p member of class B
2- Everything is passed by value (and not by reference) in Java
The Long class is immutable, so you can not pass back the value by modifying it in the called function. In your ClassB a copy is created and the original value is never changed.
If you want the caller to see the changed value, you must pass it back as return value.
The same is true for the other primitive wrappers and String.
Because Java uses pass-by-reference. This means that it passes a copy of the variable, and not a reference to the "original" one.
E.g. in C++, you can do this:
void change_var(int &x)
{
x = 2;
}
int x = 10;
change_var(x);
std::cout << x << std::endl;
This would print 2, since the reference to the variable x is being passed, and not a copy.

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.

In Java, what is the difference between the following declarations?

Considering Java. How are these 2 different and why?
public void languageChecks() {
Integer a = 5;
Integer b = new Integer(5);
change(a); // a doesn't get incremented. value is 5
change(b); // b does. value is now 6
}
public void change(Integer a) {
a++;
}
The only difference is that
Integer b = new Integer(5);
guarantees a new object is created. The first will use an instance from a cache (see Integer.valueOf()).
Both are immutable and the references to both are passed by value (as is everything in Java). So change() has no effect on either.
I'd always been taught a++ was just shorthand for a = a + 1 in which case a local variable is created named a and immediately thrown away when the method returns. There're no methods on Integer that change the value (it's immutable), and likewise no operations on primitive ints that change their value.
Neither call to change() affects the values passed in, because of auto-boxing/unboxing.
public void change(Integer a) {
// This unboxes 'a' into an int, increments it and throws it away
a++;
}
The above code seems to imply that a++ changes the value of a, since it's an object, not a primitive. However, ++ is not overloaded by Integer, so it unboxes it to be able to apply the ++operator on its int. To me the compiler shouldn't allow this.

Categories