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
Related
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.
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?
Given this code snippet:
class Ex1{
public static void main(String args[]){
int x = 10;
int y = new Ex1().change(x);
System.out.println(x+y);
}
int change(int x){
x=12;
return x;
}
}
I understand that the x in main won't get changed by the change method and return the value 22 because Java primitives are call-by-value. However, if I change all the int to Integer, making them objects and therefore theoretically call-by-value-of-reference, why does the program still return 22?
Is it possible to modify the method change such that it also modifies the variable x in main?
EDIT: new snippet
class Ex1{
public static void main(String args[]){
Integer x = 10;
Integer y = new Ex1().change(x);
System.out.println(x+y);
}
Integer change(Integer x){
x=12;
return x;
}
}
Both value and reference types are passed by-value in Java (see the Java Tutorials). This means that the passed-in reference still points at the same object as before the call, even if the internals of a method change the reference assigned to a method's parameter variable.
The primitive wrappers are all reference types, so there is no difference between their behaviour and the behaviour of any other reference type when passed as an argument to a method.
However, you can change the values inside a reference object, and those changes will be reflected after the method call completes, in the calling method. You can't do this with the primitive wrappers though: they are immutable.
public static void main(String[] args){
Foo parentFoo = new Foo(1);
System.out.println(parentFoo); // prints "instance 1, data is now 1"
changeReferenceFail(parentFoo); // prints "instance 2, data is now 2"
System.out.println(parentFoo); // prints "instance 1, data is now 1"
mutateReference(parentFoo); // prints "instance 1, data is now 3"
System.out.println(parentFoo); // prints "instance 1, data is now 3"
}
private static void changeReferenceFail(Foo myFoo) {
myFoo = new Foo(2); // assigns a new object to the myFoo parameter variable
System.out.println(myFoo);
}
private static void mutateReference(Foo myFoo) {
myFoo.setData(3); // changes the reference variable internals
System.out.println(myFoo);
}
...
class Foo {
private static int iidSeed = 0;
private int iid = 0;
private int data;
public Foo(int data) {
this.data = data;
this.iid = ++iidSeed;
}
public void setData(int data) { this.data = data; }
public String toString() {
return String.format("instance %d, data is now %d", this.iid, this.data);
}
}
You asked: "Is it possible to modify the method change such that it also modifies the variable x in main?".
You can either pass a reference object, and modify an internal field (as per mutateReference above). Or you can return a new integer and assign it to your local variableexactly as you are doing already.
Integer change(Integer x){
x=12;
return x;
}
Because this does not change what is stored inside the object Integer x, but assigns a new value to the variable x. It is not the original argument object being changed, but a new Integer object is created assigned to the variable formerly holding the original object.
As you said, when passing an object to a function, you actually pass the value of its reference. Thus, statements like myParam = something have no effect on the object passed to the method, only method calls such as myParam.mutate() can change its state. Nevertheless, Integer is an immutable class so you will not be able by any mean, to change the value of the Integer in the main.
You are passing the value of x to your method, that applies that value to another variable x. You would need to modify the correct instance of x to change it in main. This snippet changes x, although I'm sure you knew how to do this already.
class Ex1{
int x = 10;
public static void main(String args[]){
System.out.println(x);
changeX(15);
System.out.println(x);
}
void changeX(int newVal){
x=newVal;
}
}
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)
In my original code, I'm adding nodes to a tree. My goal is to somehow get access to the last node that I added in the tree (my idea was to create another object that will point to the last object (node in my original example)).
public class RandomSubClass
{
int firstNum;
}
import java.util.LinkedList;
public class RandomClass
{
LinkedList<RandomSubClass> myListOfObjects = new LinkedList<RandomSubClass>();
void addItem(int firstNum, RandomSubClass toBeReturned)
{
RandomSubClass o1 = new RandomSubClass();
o1.firstNum = firstNum;
myListOfObjects.add(o1);
// Here I was thinking that 'toBeReturned' will get same address as
// 'o1', and by changing 'toBeReturned' (in main), values in 'o1' change
//
toBeReturned = o1;
// This following commented code worked,
// but I can't use it in my original code.
//
// The reason I can't use it is because when I add a node to a tree,
// I start at the root and trace the new node's way to a new leaf,
// which makes it hard to do (simply) that.
//
//toBeReturned.firstNum = firstNum;
//myListOfObjects.add(toBeReturned);
}
}
public class Main
{
public static void main(String[] args)
{
RandomClass myList = new RandomClass();
RandomSubClass r1 = new RandomSubClass();
RandomSubClass r2 = new RandomSubClass();
myList.addItem(1, r1);
myList.addItem(2, r2);
// I would like to do that, and see changes in the node in 'myList'
//
r1.firstNum = 10;
r2.firstNum = 20;
}
}
I want to check something about the node after I add it to the tree, and if it satisfies some condition, I want to change a flag for that node.
I can re-trace the node again (starting at root), but my tree might get huge at some point and it will take time. So if I get the address of that node when I add it, and after I check my condition, I can modify the flag at that address, knowing that it will change the flag at that node (last added).
Yes, you can do this. I give you permission. :-) But your example code won't work because Java objects are passed by value, not by reference. That is, when you pass an object to a function, if you reassign that object, it has no effect on the caller. For example:
void caller()
{
String s1="Hello";
updateString(s1);
System.out.println(s1);
}
void updateString(String s1)
{
s1="Goodbye";
}
The output of this function is "Hello", NOT "Goodbye". The assignment within the updateString function does not change the value passed in by the caller.
There are (at least) three ways to do what you want.
Method 1: The simplest is to return the new object, rather than updating a parameter:
SomeObject addItem(int firstnum)
{
SomeObject o1=new SomeObject();
o1.firstnum=firstnum;
objectList.add(o1);
return o1;
}
...
void callingFunction()
{
SomeObject newObject=addItem(1);
newObject.secondnum=2;
... etc ...
}
I prefer this method what I don't need to have some other return value: it's clean and simple.
Method 2: Create a global variable and store a handle of the object there. But this method sucks, because globals suck in general. I only mention it to tell you not to do it.
Method 3: Create a wrapper to hold a reference to the object. Then pass the wrapper to the "add" function, which can update the value within the class.
class SomeObjectWrapper
{
public SomeObject someObject;
}
...
void addItem(int firstnum, SomeObjectWrapper sow)
{
SomeObject o1=new SomeObject();
o1.firstnum=firstnum;
objectList.add(o1);
sow.someobject=o1;
}
...
void callingFunction()
{
SomeObjectWrapper sow=new SomeObjectWrapper();
SomeObject newObject=addItem(1, sow);
sow.someObject.secondnum=2;
... whatever ...
}
How about doing it with a return value:
RandomSubClass addItem(int firstNum)
{
RandomSubClass o1 = new RandomSubClass();
o1.firstNum = firstNum;
myListOfObjects.add(o1);
// Here I was thinking that 'toBeReturned' will get same address as
// 'o1', and by changing 'toBeReturned' (in main), values in 'o1' change
//
....
return o1
}
In Java all object are returned/passed via parameters by address. Only the primitives types (int, float, double...) are passed by value, if you want the primitive types to be passed by address use:
-Integer instead of int
-Double instead of double
-Float instead of Float
-ect...