Workaround for passing by reference in java - java

From this book:
Find the kth to last element of a singly linked list.
One of the proposed solutions is as follows:
public class IntWrapper{
public int value = 0;
}
Node nthToLast3(Node head, int k, IntWrapper i){
if (head == null){
return null;
}
Node node = nthToLast3(head.next, k, i);
i.value = i.value + 1;
if (i.value == k){
return head;
}
return node;
}
Why do we have to create the int Wrapper class and can't we use an int directly?

What this trick does, is to wrap an int (native type) in an object (Object derived type). Everything is passed by value in Java, and for objects, the value of the reference is passed as an argument, in a sense (think of it like a pointer value in C/C++, for example).

It is impossible in Java to pass primitive values by reference. This is a restriction on the language itself.
Technically, the only things you can pass into methods are "primitives, and pointers to objects". The latter also being a form of primitive. Java possesses neither references nor const object passing.

The author uses IntWrapper instead of an int because he wants to achieve persistent state for a value between the callers and callees.
A modification to the int member of an IntWrapper instance in a callee will be visible to a caller.
With a plain int, that's not possible because it's a primitive type, and hence it will be passed by value (it will be 'copied' if I may).

The point is that you want to be able to set the value of i.
ints are in Java implemented as primitive data, they are passed-by-value. This means that the following code doesn't set a:
public void Foo () {
int a = 5;
System.out.println(a);//prints 5
setA(a);
System.out.println(a);//prints 5
}
public void setA (int a) {
a = 3;
}
Java copies the value of the variable on the stack and the copy is modified leaving the original a untouched.
By using a Wrapper, you store the int in an object. Since objects are passed-by-value from a "variable perspective", or passed-by-reference from the objects perspective, you refer to an object that contains an int. In other words, aw referers to the same instance. Because you copied the reference an not the object. Changes made by the callee are thus reflected in the view of the caller.
public void Foo () {
IntWrapper aw = new IntWrapper();
aw.value = 5;
System.out.println(aw.value);//prints 5
setA(aw);
System.out.println(aw.value);//prints 3
}
public void setA (IntWrapper aw) {
aw.value = 3;
}
This is a useful hack in Java when you want to return multiple values or modify a variable of the caller.
C# alternatively provides the ref keyword, that enable call-by-reference for primitive values.

Related

How is a Java ArrayList modified when passed as parameter to function that returns void and modified in function? May be confused on pass-by-value

I have a block of Java code that modifies an ArrayList by passing the ArrayList into a method, modifying the list in the method, and returns void. I thought that Java's pass-by-value would cause the original ArrayList to not be modified. What am I misunderstanding?
public class Question {
public static void weaveLists(LinkedList<Integer> first, LinkedList<Integer> second, ArrayList<LinkedList<Integer>> results, LinkedList<Integer> prefix) {
/* One list is empty. Add the remainder to [a cloned] prefix and
* store result. */
if (first.size() == 0 || second.size() == 0) {
LinkedList<Integer> result = (LinkedList<Integer>) prefix.clone();
result.addAll(first);
result.addAll(second);
results.add(result);
return;
}
/* Recurse with head of first added to the prefix. Removing the
* head will damage first, so we’ll need to put it back where we
* found it afterwards. */
int headFirst = first.removeFirst();
prefix.addLast(headFirst);
weaveLists(first, second, results, prefix);
prefix.removeLast();
first.addFirst(headFirst);
/* Do the same thing with second, damaging and then restoring
* the list.*/
int headSecond = second.removeFirst();
prefix.addLast(headSecond);
weaveLists(first, second, results, prefix);
prefix.removeLast();
second.addFirst(headSecond);
}
public static ArrayList<LinkedList<Integer>> allSequences(TreeNode node) {
ArrayList<LinkedList<Integer>> result = new ArrayList<LinkedList<Integer>>();
if (node == null) {
result.add(new LinkedList<Integer>());
return result;
}
LinkedList<Integer> prefix = new LinkedList<Integer>();
prefix.add(node.data);
/* Recurse on left and right subtrees. */
ArrayList<LinkedList<Integer>> leftSeq = allSequences(node.left);
ArrayList<LinkedList<Integer>> rightSeq = allSequences(node.right);
/* Weave together each list from the left and right sides. */
for (LinkedList<Integer> left : leftSeq) {
for (LinkedList<Integer> right : rightSeq) {
//This is the part I don't understand
ArrayList<LinkedList<Integer>> weaved = new ArrayList<LinkedList<Integer>>();
weaveLists(left, right, weaved, prefix);
result.addAll(weaved);
}
}
return result;
}
}
I would expect that the weaved array would not be modified when the result.addAll(weaved) is called, but weaved array is modified after the call to weaveLists(), even though it returns void.
You create a weaved reference to an ArrayList object that stored in memory. When you call new operator then a new object allocated in the memory. Then you pass the reference weaved to the weaveLists() method.
This method have a reference result, but this is only a reference that refer to the same object in the memory, because only new operator allocate a new memory. So, the weaveLists() method modify your original ArrayList. It is a major feature that you should understand, I suggest you to read the difference between pass-by-value and pass-by-reference.
To answer the question in short - you are misunderstanding what does the pass-by-value mean in Java.
If you pass an object (list in this case) and manipulate it's elements without changing it's reference, it is the same object you passed, nothing changed on the object (list) itself, it has the same reference it had when passed to function, but changes do apply to any of the elements being manipulated.
Pass by value in this context only means that if you created a new instance of a given list within the function and then manipulated it - no changes would apply on original list, since that would be observed as a local variable, not the passed one.
Check top answers to this question, or just read some java basics related to pass-by-value. Use this blog, or any other that you might like more.

Object value doesn't change

class smth{
public static void main(String[] args){
private Integer x = new Integer(17);
inc(x);
System.out.print("x="+x);
}
public static void inc(Integer x){
x++;
System.out.println("n="+x);
}
}
output:
n=18;
x=17;
Integer is an object and I don't understand why the value of x did not change in this case.
Cause Integer is immutable object. When you send it to method, new reference to it is created. When you do increment, reference inside method is reassigned to new Integer with value 18 but reference inside main is still referencing to old Integer with value 17.
Integer is immutable. The x++ creates a new object, and rebinds x to refer to it. The change does not propagate back to the caller since the reference to the original x was passed by value.
Any wrapper classes are immutable class.
Because x++, on an Integer object, actually means:
int temp = x.intValue();
temp++;
x = Integer.valueOf(temp);
The x variable is being assigned a new Integer instance. And since parameters are passed by value, the original reference stays unmodified.
It is because Java passes objects to methods by value and not by reference. Upon completing the method call, the object value will be the same in the calling method as it was before passing it. Within the called method, the value can change but the scope of the change is the method to which it was passed.
This is because Integer, a wrapper over the primitive int, is immutable, and Java passed object references by value. Any change made to the object reference inside the method has no effect on the object passed in: the reference is replaced with a reference to a new object, yet the original remains intact because it is immutable.
To address this issue, you need another level of indirection - you can use an array, a mutable int from apache commons, or roll your own suitably designed class.
public static void main(String argv[])
MutableInt x = new MutableInt (17);
inc(x);
System.out.print("x="+x.intValue());
}
public static void inc(MutableInt x){
x.add(1);
System.out.println("n="+x.intValue());
}
It is because the object modifying inside the method incis not the same as the one printed outside this method.
Inside the method inc x is a reference which points to an object. When you run x ++, that reassigns X to reference a new Integer object, with a different value. Thus, you are not modifying your original 'x' variable declared on the main.
You have to return the "pointer" to the new integer object:
public static int inc(Integer x){
x++;
System.out.println("n="+x);
return x;
}
public static void main(String argv[])
Integer x = new Integer(17);
x = inc(x);
System.out.print("x="+x);
}
An Integer, is a Object that contains a single int field. An
Integer is much bulkier than an int. It is sort like a Fedex box to
contain the int. Integers are immutable (source)

Java Heap and Pass By Value

I am a little confused as to how my Java program is allocating memory. Below is a typical situation in my program. I have an object created on the Heap inside of a class which I pass to other functions inside of other classes.
public class A {
private List<Integer> list = new ArrayList<Integer>();
public A() {
for(int i = 0; i < 100; i++)
list.add(i);
}
public void foo() {
B b = new B();
b.bar(this.list);
}
}
public class B {
A a = new A();
public int bar(List<Integer> list) {
list.add(-1);
return list.size();
}
public int getSize() {
List<Integer> list = a.list;
return a.size();
}
}
My question(s) are about how the memory is used. When A's list gets passed to B.bar(), does the memory get copied? Java is pass-by-value so I assumed the B.bar() function now contains a copy of the list which is also allocated on the heap? Or does it duplicate the list and put it on the stack? Or is the list duplicated at all? Similarly what applies to these memory questions inside of B.getSize()?
It's probably clearer to say that in Java, object references are passed by value.
So B gets a copy of the reference (which is a value) to the List, but not a copy of the List itself.
You can easily prove this to yourself by getting B to modify the List (by adding or removing something), and observing that A's List also changes (i.e. it is the same List).
However, if you change B's reference to the List (by creating and assigning a new List to it), A's reference is unchanged.
Java is pass-by-value, but the value of an expression or variable is always either a primitive or a reference. A reference, in turn, is either null or a pointer to some object.
In your case: private List<Integer> list = new ArrayList<Integer>(); declares list as having a reference type, and makes its value a pointer to a newly allocated ArrayList object.
When you use list as an actual argument, for example on the b.bar(this.list); call, the formal argument list in b.bar is initialized with a copy of that pointer. That is, bar's formal argument points to the same ArrayList object as A created. The ArrayList object is not copied.
Java is pass-by-value, dammit!
However, you only ever have access to references to Objects. In that sense, you are passing Object references by value.

pass by reference/value - simple example

I know this issue has been addressed many times - but my Java/C++ knowledge is so weak I can barely understand the answers :-( ... what I'd really like is just a super simple example.
In C++ I could write the following:
void func()
{
int x = 3;
add_one(x);
// now x is 4.
}
void add_one(int &var)
{
var++;
}
What I'd like to see now is the simplest way to achieve the same effect with java.
You can't directly. The closest you can get is to put the value in an object, and pass the reference (by value, so the reference gets copied) into the method.
void func()
{
int x = 3;
int[] holder = [x];
add_one(holder);
// now holder[0] is 4. x is still 3.
}
// container here is a copy of the reference holder in the calling scope.
// both container and holder point to the same underlying array object
void add_one(int[] container)
{
container[0]++;
}
Here I use an array, but the wrapper can be any object.
In java method arguments are pass-by-value, and can't be changed in the function. You must wrap the int - or any other primitive type - in an Object or an array. Passing an Object or an array as a method argument passes a reference which can be used to modify the object.
Java already has Object based wrappers for primitive types, e.g. Integer, but these are immutable by design. Some libraries provide mutable versions of these wrappers; you can also create your own:
public class MutableInt
{
private int val;
public MutableInt(int val)
{
this.val = val;
}
public void setValue(int newVal)
{
this.val = newVal;
}
public int getValue()
{
return this.val;
}
}
void func()
{
int x = 3;
MutableInt wrapper = new MutableInt(x);
add_one(wrapper);
}
void add_one(MutableInt arg)
{
arg.setValue(arg.getValue() + 1);
}
You cannot do this. Java is only pass by value. Primitives are obvious, but the thing that's passed for objects is a reference, not the object itself.
As you can see from the other answers, Java is purely pass by value. Objects are passed by what some call "value-reference". Since an object in java is simply a pointer reference, you can think of the "value" as the address where the object lives on the heap. So when you make a method call, you're copying the "value", aka address, to the method parameter:
Object x = new Object();
foo(x);
During object creation
Heap --> allocate Object (5000)
Variable Declaration
Stack --> allocate local variable (1000)
Variable Assignment
Stack address 1000 set to 5000 (to point to object instance)
So you can see that there are two separate memory allocations here. The "value" of the variable is considered to be it's address on the heap.
Method Call
Stack --> allocate method parameter 8000
Stack address 8000 set to same value as passed parameter 5000
This is why if you reassign an object instance in a method, it does not propagate back to the caller. You would have changed the heap location at stack location 8000. And the calling method's stack location 1000 still has the value 5000 (the original object instance).
Think of it like this in C:
void method(myobject * obj);
You can certainly change fields of "obj", and you can do this locally:
obj = new myobject();
But the caller will still see the original value it passed.
Java has no analog to the & reference operator.
And there are built in classes which can be used for the your purposes. AtomicInteger, AtomicLong, etc... are mutable, though you may suffer a performance hit due to synchronization involved.
I would recommend a generic ValueHolder class to account for all situations where you want to simulate pass by reference:
public class ValueHolder<T> {
private T value;
// getter/setter/constructor
}
Java allows copy by reference for objects and copy by vlaue for primitive types (int,float,etc..). This is so by default and is not subject to change. If you need to change the value of an int inside a function, then you can use the class Integer for example
public int getOneMore(int val) {
return val + 1;
}

What does AtomicReference.compareAndSet() use for determination?

Say you have the following class
public class AccessStatistics {
private final int noPages, noErrors;
public AccessStatistics(int noPages, int noErrors) {
this.noPages = noPages;
this.noErrors = noErrors;
}
public int getNoPages() { return noPages; }
public int getNoErrors() { return noErrors; }
}
and you execute the following code
private AtomicReference<AccessStatistics> stats =
new AtomicReference<AccessStatistics>(new AccessStatistics(0, 0));
public void incrementPageCount(boolean wasError) {
AccessStatistics prev, newValue;
do {
prev = stats.get();
int noPages = prev.getNoPages() + 1;
int noErrors = prev.getNoErrors;
if (wasError) {
noErrors++;
}
newValue = new AccessStatistics(noPages, noErrors);
} while (!stats.compareAndSet(prev, newValue));
}
In the last line while (!stats.compareAndSet(prev, newValue)) how does the compareAndSet method determine equality between prev and newValue? Is the AccessStatistics class required to implement an equals() method? If not, why? The javadoc states the following for AtomicReference.compareAndSet
Atomically sets the value to the given updated value if the current value == the expected value.
... but this assertion seems very general and the tutorials i've read on AtomicReference never suggest implementing an equals() for a class wrapped in an AtomicReference.
If classes wrapped in AtomicReference are required to implement equals() then for objects more complex than AccessStatistics I'm thinking it may be faster to synchronize methods that update the object and not use AtomicReference.
It compares the refrerences exactly as if you had used the == operator. That means that the references must be pointing to the same instance. Object.equals() is not used.
Actually, it does not compare prev and newValue!
Instead it compares the value stored within stats to prev and only when those are the same, it updates the value stored within stats to newValue. As said above it uses the equals operator (==) to do so. This means that anly when prev is pointing to the same object as is stored in stats will stats be updated.
It simply checks the object reference equality (aka ==), so if object reference held by AtomicReference had changed after you got the reference, it won't change the reference, so you'll have to start over.
Following are some of the source code of AtomicReference. AtomicReference refers to an object reference. This reference is a volatile member variable in the AtomicReference instance as below.
private volatile V value;
get() simply returns the latest value of the variable (as volatiles do in a "happens before" manner).
public final V get()
Following is the most important method of AtomicReference.
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
The compareAndSet(expect,update) method calls the compareAndSwapObject() method of the unsafe class of Java. This method call of unsafe invokes the native call, which invokes a single instruction to the processor. "expect" and "update" each reference an object.
If and only if the AtomicReference instance member variable "value" refers to the same object is referred to by "expect", "update" is assigned to this instance variable now, and "true" is returned. Or else, false is returned. The whole thing is done atomically. No other thread can intercept in between. As this is a single processor operation (magic of modern computer architecture), it's often faster than using a synchronized block. But remember that when multiple variables need to be updated atomically, AtomicReference won't help.
I would like to add a full fledged running code, which can be run in eclipse. It would clear many confusion. Here 22 users (MyTh threads) are trying to book 20 seats. Following is the code snippet followed by the full code.
Code snippet where 22 users are trying to book 20 seats.
for (int i = 0; i < 20; i++) {// 20 seats
seats.add(new AtomicReference<Integer>());
}
Thread[] ths = new Thread[22];// 22 users
for (int i = 0; i < ths.length; i++) {
ths[i] = new MyTh(seats, i);
ths[i].start();
}
Following is the github link for those who wants to see the running full code which is small and concise.
https://github.com/sankar4git/atomicReference/blob/master/Solution.java

Categories

Resources