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?
Related
Like the code shows, as variable x is substituted to list, when the new instance of ListNode is substituted to x.next, it is reflected on both x and list(refer to the comment 1). I think this is because x refers to list.
However, when the new instance is substituted to x, it is reflected on only x, not list(refer to the comment 2).
Could you explain why this happens?
public class Sample {
public static void main(final String[] args) {
final ListNode list = new ListNode(0, null);
ListNode x = list;
//1.ListNode new instance is substituted for both x and list as x refers to list
x.next = new ListNode(1, null);
//2.ListNode new instance is substituted only for x, not list
x = new ListNode(1, null);
}
}
class ListNode {
int data;
ListNode next;
ListNode(final int data, final ListNode next) {
this.data = data;
this.next = next;
}
}
https://github.com/indrabasak/Books/blob/master/Head%20First%20Java%2C%202nd%20Edition.pdf
Read chapter 3 "Primitives and references" from this book. Your life will become much easier.
Unlike other languages like C++, most Java variables (except primitives) are references to Objects. So, after:
ListNode x = list;
both x and list reference the same object (x == list). Any modification you'll do (like changing the x.next field) will apply to both variables.
However, you can always change the object x is referencing (but not list, since it is final) and you do it with:
x = new ListNode(1, null);
After that x != list.
You can test with a primitive type (like int) to see what changes.
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)
creating a doubly linked list with one node that points to itself
public DList(){
Dnode sentinel= new DNode(sentinel, null, sentinel);
}
for reference, Dnode constructor takes DNode(Dnode p, Object 0, Dnode n)
Is this valid code?
No, this is not valid.
You can't cant use sentinel variable in the expression that defines it.
You can however have a constructor, which makes the previous and next elements be itself (this):
class DList {
DList previous, next;
public DList() {
previous = this;
next = this;
}
}
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
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...