How to implement pass by reference in java explicitly? - java

I know that java does not support pass by reference. But still is there any possibility to implement it in any other ways if not directly as in C/C++?

Nope. You can't do it. It's not something you can "implement". It's a fundamental aspect of the language.

If what you're trying to do is to have a "reference" to a primitive value which you can pass around, so you can modify the primitive's value inside methods and have the changes be visible outside said methods...
... just pass an array containing the primitive, like this:
// By value
int value = 1;
changeValue(value); // changes value to 5
System.out.println(value); // prints 1
// By "reference"
int[] reference = {1};
changeValue(reference); // changes value inside "reference" to 5
System.out.println(reference[0]); // prints 5
// Methods
void changeValue(int value) { value = 5; }
void changeValue(int[] reference) { reference[0] = 5; }
Bear in mind that this is not "pass by reference". Java is not passing a reference to the value, Java is passing the value of the array's reference.
You can read Is Java "pass-by-reference" or "pass-by-value"? for a better discussion about this.

Pass-by-value was by design: f(x) will maybe alter the internals of the value of x, but x will not get another value. _For instance you cannot assign null to x inside f, using the formal parameter of f.
There is the possibility of in-out parameters which in java can be done by the function's result:
insertInNodes is such a method.
public class SortedLinkedList<T extends Comparable<T>> {
private static class Node { ... }
Node head;
int size;
public void insert(T data) {
head = insertInNodes(head, data);
}
private Node insertInNodes(Node node, T data) {
if (node == null || data.compareTo(node.data) < 0) {
++size;
return new Node(data, node);
}
if (data.compareTo(node.data) > 0) {
node.next = insertInNodes(node.next, data);
}
return node;
}
}
Pass-by-reference needs to either fake it: pass a container object and then the component is actually a reference. For instance an array with one element or a wrapper class like Atomic<String>.
Pass-by-reference in a more pure form could be realized by passing a getter and setter of the wanted "variable."
public void insert(T data) {
insertInNodes(this::getHead, this::setHead, data);
// Or insertInNodes(() -> head, (n) -> head = n, data);
}
private void insertInNodes(Supplier<Node> getter, Consumer<Node> setter, T data) {
if (getter.get() == null || data.compareTo(getter.get().data) < 0) {
++size;
setter.apply(new Node(data, getter.get()));
}
if (data.compareTo(node.data) > 0) {
// insertInNodes(() -> node.next, (n) -> node.next = n, data);
// or
insertInNodes(node::setNext, node::getNext, data);
}
return node;
}
Is this usable? No, only in specific use-cases.

Related

Why is there no difference in output for the below code?

I am pretty new to java and getting confused with the below code:
public class NewNode {
NewNode next = null;
int data;
public NewNode(int data) {
this.data = data;
}
public void addToNode(int data){
NewNode n = this;
System.out.println(n);
NewNode newlyCreated = new NewNode(data);
}
}
but even after changing the addToNode method as below:
public void addToNode(int data){
NewNode newlyCreated = new NewNode(data);
NewNode n = this;
System.out.println(n);
}
The output of n doesn't change . If,this keyword refers to the current instance of the object then shouldn't newlyCreatedNode be the output in the second scenario.Please help....
According to the doc tutorials:
Within an instance method or a constructor, this is a reference to the current object — the object whose method or constructor is being called.
So in both example this refers to the object you call addToNode() on. The fact that you create an object within the method is irrelevant. So:
public void addToNode(int data){
NewNode n = this; //Refers to the object this method is called on
System.out.println(n);
NewNode newlyCreated = new NewNode(data); //Creates a random object
}
public void addToNode(int data){
NewNode newlyCreated = new NewNode(data); //Creates a random object
NewNode n = this; //Refers to the object this method is called on
System.out.println(n);
}
this is the current instance i.e. the instance that invokes the addNode method.
Thus when you create a new Node by NewNode newlyCreated = new NewNode(data); it just creates a new Node locally. The current instance(i.e. this) remains the same.
Your output will change if you do this.data = data i.e. changing the data field of current instance
EDIT: Also you need to override the toString method to print NewNode otherwise it'll print default Object's toString method
Okay, take a look at this piece of code. Let me try to give you a simpler example.
Assume that we have a class like this:
class A {
int data;
void printData() {
System.out.println(this.data);
}
}
And then you create two instances of A like this:
A a1 = new A(); a1.data = 10;
A a2 = new A(); a2.data = 12;
So there are now two objects a1 and a2 which are of the A type.
Now let's call the printData() method on them. How would you do it?
a1.printData();
a2.printData();
Now look at the first print call, it is happening on the a1 object. So now control goes into the printData method, where the this will resolve to a1, so this.data will be same as a1.data from outside.
Now in the second call, yes you get it right. It is being invoked on a2 object, so inside the method printData, a2 will be assigned to this.
This is what it means when they say that this resolves to the current object.
Got it now?

Java and pass by reference

I'm not terribly familiar with Java, I'm fiddling with a simple binary tree and ran into something that I dont understand...
in the following snippet, Add() passes AddHelper() a number and a reference to the root node, mRoot. However, mRoot is always null, even after the first call to AddHelper()
If, however, I change I change AddHelper() such that it uses mRoot directly (instead of being passes in by reference), then it works... I dont understand why/how this would be any different, functionally.
Node mRoot;
public void Add( int num ) {
AddHelper(num, mRoot);
}
private void AddHelper( int num, Node node ){
// if I change 'node' to 'mRoot', it works. why?
if ( node == null ) {
node = new Node(num);
}
else {
...
}
assuming you have declared mRoot as a Node in your class already let me answer your question.
java is always pass by value when you pass mRoot to your method you are passing bytes that are referring the object in the heap. for example when you do this with a primitive variable
int i =5;
int j=i;
the bytes stored in i is transferred to j. similarly when you do this
Object obj = new Object();
Object newObj = obj;
the bytes stored in the reference variable obj is getting transferred to the reference newObj. as obj holds the reference to the Object instance the same reference is held by newObj.
you can see that
i = 5;
j=i;
j=10; // this doesn't change the i value
same way
obj = new Object();
newObj = obj;
newObj = new Object(); // this doesn't change the obj
hope you understood.
EDIT:
to answer your question in the comment, consider the following code.
class Sample {
Object originalObj;
public static void main(String[] args) {
System.out.println(originalObj); // prints null
tryToCreateInstance(originalObj);
System.out.println(originalObj); // still prints null
createInstance(originalObj)
System.out.println(originalObj); // prints the object hashcode
originalObj = returnInstance(originalObj);//returns the same reference as originalObj
//is already initialized, if it had been null
// this would have returned a new object
System.out.println(originalObj); // prints the object hashcode
}
public void tryToCreateInstance(Object obj1){
if(obj1==null) {
obj1 = new Object(); // relate this with my answer above
// this wont change what originalObj refers
}
}
public void createInstance(){
if(obj==null) {
originalObj = new Object(); // refers to the instance variable originalObj
// hence will affect what originalObj refers
}
}
public Object returnInstance(Object obj1) {
if(obj1==null) {
return new Object(); // returns a new object
}
else {
return obj1;
}
}
}
This is because you are not setting mRoot in your first case. Even though you are setting a node to new Node(num);, you are not setting mRoot. To set mRoot:
if ( node == null ) {
node = new Node(num);
this.mRoot = node; //depending on your logic
}
else {
...
}
Jave is pass by value always. For example, mRoot points to Object X. When you pass mRoot to AddHelper, now node will point to Object X. And then you re-initialize node to new Object (say Object Y). But the previous mRoot still points to Object X.
Hence you need to set mRoot back to Object Y.
When we say pass by value, for primitives the value is copied. But in case of Objects, the object reference is copied (but not the object is duplciated). So if you pass a String reference to a function, the function argument will point to the same String only (as it has copied the object reference which can be though of as a pointer)

How to implement a basic pointer

I know here is no pointer in Java. But how do I change a value in the calling scope? For instance, I want to write a function that takes an integer num, set the integer to 0 if it's greater than 21, otherwise do nothing.
In the main, my code is as follow:
int a=34;
KillOver21(a);
System.out.print(a);
I expect an 0.
Java is pass by value, so a copy of the parameter a is sent to the method, so modification to a in the method will not affect the original argument a in main
The max you can do is return int from KillOver21(a) method
int z = KillOver21(a); // This will return 0
System.out.print(z);
But you can achieve something like that with custom objects, say you have a class
class AHolder {
public int a;
}
then you can expect AHolder instance to change
public static void main(String [] args) {
AHolder a = new AHolder();
a.a = 34;
killOver21(a);
System.out.println(a.a);
}
public static void killOver21(AHolder b) {
if(b.a > 21) {
b.a = 0;
}
}
Since in the latter (even if its Pass by Value) , the reference is copied and both reference point to same object. So changes made inside the killOver21 method actually changes the object.
It is simply not possible, Java supports pass by value. int a's value will be copied to the function.
You could use Object instead of primitive where the reference value will be copied to your function by which you can get the actual object and modify it.
Fundamentally impossible in Java, period. int are immutable, and passed by value. You would need to create a mutable int type:
class MutableInt {
private int value;
public MutableInt(int value) { this.value = value; }
public getValue() { return this.value; }
public setValue(int value) { this.value = value; }
}
Then:
void KillOver21(MutableInt m) {
if(m.getValue() > 21) { m.setValue(0); }
}
However, be aware the mutable types that represent concepts that are defined by their value rather than their identity are generally an extremely bad idea. But, this is the only way to achieve what you're trying to achieve. Again, I caution you with the strongest words: what you're doing is a bad idea. You should find another way.
Doc, it hurts when I do this.
Then don't do that!
The simpliest way (quick&dirty) is to put value within an array
int holder[] = new int[]{ a};
KillOver21(holder)
System.out.printf( "value=[%d]", holder[0] );
void KillOver21(int holder[] ) {
holder[0] = 0;
}

Unexpected output in java

I have written a code -
// Node Class
class aNode {
// Node Contents
int NodeInt;
char NodeChar;
// constructor
aNode() {
}
aNode(int x, char y) {
NodeInt = x;
NodeChar = y;
}
}
class MainClass {
static aNode node = new aNode();
public static void main(String[] args) {
node = null;
function(node);
if (node == null) {
System.out.println("Node is null");
}
}
static void function(aNode x) {
if (x == null) {
System.out.println("Node is null");
}
x = new aNode(5, 'c');
System.out.println(x.NodeInt);
System.out.println(x.NodeChar);
}
}
I expected the output to be -
Node is null
5
c
but when the program returns to main, the value of node is set to null again. So I get the output to be -
Node is null
5
c
Node is null
Please help me modify the code to get desired output. Any help will be appreciated!
You should know, that aNode node and aNode x are references to different objects. It is one of Java features - passing only by value. It mean, that when you are calling
function(node);
you are not passing node reference to method function(...), you are creating new reference to the same object. But in line
x = new aNode(5,'c');
you are setting reference x to new object. So, node still references to null and x references to new aNode.
To get more about passing params in Java, read next article.
Reference data type parameters, such as objects, are also passed into
methods by value. This means that when the method returns, the
passed-in reference still references the same object as before.
However, the values of the object's fields can be changed in the
method, if they have the proper access level.
Real pass-by-reference is impossible in Java. Java passes everything by value, including references..
So you have to slightly change your code to get the desired output:
class aNode{
//Node Contents
int NodeInt;
char NodeChar;
//constructor
aNode(){
}
aNode(int x, char y){
NodeInt = x;
NodeChar = y;
}
}
class JavaApplication8{
static aNode node = new aNode();
public static void main(String[] args){
node = null;
node=function(node);
if(node == null){
System.out.println("Node is null");
}
}
static aNode function(aNode x){
if(x == null)
{
System.out.println("Node is null");
}
x = new aNode(5,'c');
System.out.println(x.NodeInt);
System.out.println(x.NodeChar);
return x;
}
}
Output:
Node is null
5
c
You are passing a static object, but in the method function(), you are not changing the value of object node. You are changing the value of other object only. So in main, the value of node s null only.
In general, this is because Java passes a copy of the reference to the aNode object to your method. Changing this reference will not change the original reference.
Inside function(), x is simply a local variable. When you reassign a reference in Java, you are modifying the content of the reference itself, not the one of the referred object. There's no way in Java to pass the address-of an object. If you want such a behavior, you can try with a generic class like Wrapper

How Java "pointers" work?

Lets say this is the C++ code:
void change(int& x){
x++;
}
or
void change2(int* a){
*a++;
}
Both will change the global x, right?
So how can I do something like that in java?
Specifically, I want to point to a Vector object
But since Java has no pointers, I'm not sure what to do.
From searching the internet I saw people saying that Java does that in some other way, but I haven't found any real example.
Thanks for
help!
In Java, instead of pointers you have references to objects. You cannot pass a primitive type by reference, but you can wrap a primitive type inside an object and then pass a reference to that object.
Java provides the type Integer which wraps int, however this type is immutable so you cannot change its value after construction. You could however use MutableInt from Apache Commons:
void change(MutableInt x) {
x.increment();
}
The change to x will be visible to the caller.
Specifically, I want to point to a Vector object
When you write Vector v = ...; you are assigning a reference to a vector to the variable v. A reference in Java is very similar to a pointer. References are in fact implemented internally using pointers.
Java uses pass by value. When you pass a vector to a method, you are actually copying a reference to that vector. It does not clone the vector itself. So passing a reference in Java is very similar to passing a pointer in C++.
With Java you cannot pass primitive types like int by reference, they are passed only by value.
The only things you can do is to find artifices to do that, because instead Objects are passed by reference. Here two examples.
Use an array of single value, like this
int[] value = new int[1];
value[0] = 2;
// call a method
obj.setValue(value);
// and in setValue
public void setValue(int[] value) {
value[0] = 5;
}
Or second approach use an holder class:
public class Holder<T> {
public T value;
public Holder(T value) {
this.value = value;
}
}
// then use it in this way
Holder<Integer> h = new Holder<Integer>(2);
obj.setValue(h);
// and in setValue
public void setValue(Holder<Integer> h) {
h.value = 5;
}
In this case I use an holder class implements with generics but you can have a simple holder too, only for integer. For example:
public class IntHolder {
public int value;
public IntHolder(int value) {
this.value = value;
}
}
Java always passes by value and there are no global variables as in the C++ sense. So if you want to do the same as in C++ you need to return the new value.
Thusly:
public int change(int x) {
return ++x;
// or
// return x + 1;
}
To test it:
int x = 2;
change(x);
System.out.println(x); // returns 2
x = change(x);
System.out.println(x); // returns 3
So it doesn't make any sense to let the method be called change, it is more sensible along the lines of calculateThisInt.
Java does pass objects by value. But as Mark Byers mentions the Integer class is immutable and you could use MutableInt from Apache Commons library. To describe how this works you could implement it yourself for your example:
public class MyInt() {
public int i;
public void setInt(int i) {
this.i = i;
}
public int getInt() {
return this.i;
}
public int increment() {
this.i++;
}
}
You need to change your change function to have the above MyInt object as argument:
public void change(MyInt i) {
i.increment();
}
Usage:
MyInt x = new MyInt();
x.setInt(2);
change(x);
System.out.println(x.getInt); // returns 3
In your case you want to change a Vector object...
public void changeVector(Vector v) {
// anything you do with 'v' will change it even
// for the scope that called this method
}
// Usage:
Vector v = new Vector();
changeVector(v);
// v should be changed after calling change vector method
Hope this all makes sense.
Both will change the global x, right?
So how can I do something like that in java? Specifically, I want to
point to a Vector object
The question is somewhat vague, but I got the impression that you ultimately want a global Vector that you can keep stuff in?
Many ways to do that, but one of the simplest is to have a static field in a class, with public static methods for accessing it. (Or simply a public static field which is accessed directly, but that really wouldn't be idiomatic in Java.)
public class Foo {
private static List<Integer> globalVector = new Vector<Integer>();
public static void add(int number){
globalVector.add(number);
}
// ... plus whatever other accessors to the global list that you need
}
Anywhere else in code:
Foo.add(23); // modifies the global vector
(Btw, Vector is kinda obsolete, and typically we'd use ArrayList in its place now. As the Javadoc says, it's been retrofitted to implement the List interface, which I also used in the example.)
While you can't replace an object that's been passed to a function, you can change its state by altering fields directly or calling methods. If you need something like a pointer to a primitive, wrap it in an object. To follow your code, you could do this:
public class IntPointer {
public int value;
public IntPointer(int value) {
this.value = value;
}
}
Then elsewhere you could say:
public static void change(IntPointer ipoint) {
ipoint.value++;
}
public static void main(String[] args) {
IntPointer a = new IntPointer(10);
change(a);
}
This might seem a bit awkward, but it hasn't come up for me as often as you'd think. I'd be more likely to do something like this:
public class ABPair {
private int a = 0;
private int b = 0;
public static void changeA() {
a++;
}
public static void changeB() {
b++;
}
}
So that elsewhere I can say:
public static void main(String[] args) {
ABPair ab = new ABPair();
if (ACondition) {
ab.changeA();
}
}
In other words, my data tends to already be wrapped in some sort of object, and I tend to use the data object's methods to mediate any changes.
Java supports what it calls "references". References act alot like pointers in C/C++-like languages. They don't act the same way "references" work in those languages.
The major differences between a pointer in C and a reference in Java are:
You can't do pointer arithmetic in Java (i.e. you can't "add" or "subtract" from a Java reference, you can only dereference it or compare it with another one).
You can't cast it to an incompatible type: Java is strongly type-safe, you can't "re-interpret" the bytes in memory as some other object.
For some uses of pointers this has no real effect (for example linked lists work pretty much the same in both languages), for others the difference is quite major (arrays in C are just fancy pointer arithmetic, in Java they work quite differently).
So in a way Java references could be called "restricted pointers".

Categories