This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java, pass-by-value, reference variables
I am a bit confused on how exactly JAVA pass by value works with object. For e.g. if I pass a object as a parameter to the method. I understand that its address is passed as value. Ok, is a duplicate of the object is kept at the original place form where the object is passed, because if I create a new reference to the object in the called API and change something in it, it doesn't get reflected in my caller API.
Below is a typical piece of code where I try to delete a tree but it's still there.
public class DeleteTree {
public static void main(String[] args) {
Node root = new Node(5);
for(int i = 0 ; i < 10 ; i++){
if(i == 5) continue;
root.insertNode(i);
}
deleteTreeNonRecursive(root);
System.out.println(root.key);
}
public static void deleteTreeNonRecursive(Node root){
Queue<Node> q = new LinkedList<Node>();
q.add(root);
while(!q.isEmpty()){
Node temp = q.poll();
if(temp.leftChild != null)q.add(temp.leftChild);
if(temp.rightChild != null)q.add(temp.rightChild);
temp = null;
}
}
Expected O/P: nullpointer exception.
Actual O/P: 5.
In Java you always pass by value the reference to the object (which is itself allocated onto the heap). No duplication occurs because you are just passing pointers around.
In your example you are just setting temp = null but this indeed does nothing just because temp is a pointer to a Node but it's a variable local to the function, when you set it to null the original object is not touched at all just because you are just modifying the value of the reference without modifying the referenced object.
To delete the tree this is the only thing you need:
Node root = new Node(5);
for(int i = 0 ; i < 10 ; i++){
if(i == 5) continue;
root.insertNode(i);
}
root = null;
Java always uses pass by value. It's the value of the reference that is passed when it comes to object references. When you pass an object reference, it's a copy of the reference value which is passed. Using that, you can always access the object and change its properties (wherever applicable), but assigning that reference to another object or null has no consequences to the original reference in the calling method obviously.
Related
In this Trie implementation, children array elements are assigned null value individually using a for loop.
TrieNode(){
isEndOfWord = false;
for (int i = 0; i < ALPHABET_SIZE; i++)
children[i] = null;
}
However, by default, when we create an array of reference types in Java, all entries will have default value as null which is:
TrieNode[] children = new TrieNode[ALPHABET_SIZE];
The above step assigns default values of children array entries as null.
Is it required to have null assignment once again in the for loop inside that TrieNode constructor?
No it's not required - for each class variable, instance variable, or array component Java will always assign reasonable default value (like 0 for int or null for Object) - you can read more here
However notice that for local variables it's not guaranteed
The compiler will assign a reasonable default value for fields of the above types; for local variables, a default value is never assigned.
and that's why you are forced to initialize it manually
public void f() {
String s;
System.out.println(s); // will cause Error: java: variable s might not have been initialized
}
Ok, so i have to create a recursive method for counting the nodes in a tree, and i did this (variable names are in portuguese, sorry):
public int contaNos(Arvbin r) {
Integer cardinalidade = 0;
contaNosPrivado(r, cardinalidade);
return cardinalidade;
}
private void contaNosPrivado(Arvbin r, Integer cardinalidade) {
if (r==null) {
return;
}
cardinalidade=cardinalidade+1;
contaNosPrivado(r.esq, cardinalidade);
contaNosPrivado(r.dir, cardinalidade);
return;
}
Arvbin is the binary tree, esq and dir are the left and right references to the tree's branches.
I thought this would work, but for some reason when i try to run it, it returns 0. I've usen a little bit of debugging and i think the issue is that when the methods finish and come back to the original non-recursive one, the cardinalidade variable is set to 0. I'm not sure if it's because autoboxing is messing with my Integer and turning it into an int, and then when i call the method it passes a copy of the value instead of the reference to the existing object, and i don't know how to fix it. If anyone could help, i'd greatly appreciate it
The problem is that wrapper classes are immutable in Java. cardinalidade is just a parameter of contaNosPrivado here and, unfortunately, cannot act as an argument like other object type parameters can, i.e. this local reference cannot change inner fields of the object that initial reference refers. Any change to it affects it only the way it affects any primitive local variable.
What exactly happens inside your contaNosPrivado:
On invocation, it is indeed supplied a reference to an Integer object. This reference is assigned to a local variable named
cardinalidade.
In this line:
cardinalidade=cardinalidade+1;
this object is first unboxed to a primitive int variable, this variable is incremented afterwards, and
finally the result is reboxed into a new Integer object which is
then assigned to cardinalidade. There is no way to 'increment'
original object, even if you use the increment operator:
cardinalidade++;
Any further processing applies to the newly created Integer object and doesn't affect the reference passed to contaNosPrivado.
To achieve your goals, use something like this instead:
static int contaNosPrivado(Arvbin r) {
if (r == null)
return 1;
else
return contaNosPrivado(r.esc) + contaNosPrivado(r.dir);
}
As #John McClane has pointed out, you can't pass an Integer argument by reference, only by value.
But there's also no need for a private helper method, you can just simplify it all to a single method:
public int countLeaves( BinaryTreeNode n )
{
return n == null? 0 : ( countLeaves( n.rightLeaf ) + countLeaves( n.leftLeaf ) );
}
Or (excuse my poor Portugese):
public int contaNos( Arvbin r )
{
return r == null? 0 : ( contaNos( r.esq ) + contaNos( r.dir ) );
}
In Java programs, is it right to set an object equal to another one? To be more specific, I'm studying binary trees and I noticed in the following code:
public Node find(int key)
{
Node current = root;
while(current.iData != key)
{
if(key < current.iData)
{
current = current.leftChild;
} else {
//...
}
}
}
that both Node current = root; and current - current.leftChild; are setting an object equal to another one. Is this right?
setting an object equal to another one. Is this right?
No, that's not right.
What's actually happening is, you're changing the reference of one variable to another object.
So:
Node current = root; // "current" will point at the same object as `root`.
and
current = current.leftChild; // "current" will point at the same object as `leftChild`.
note -
When assigning primitive types with = is a completely different behaviour when assigning reference types with =.
First of all, you need to need a basic concept in Java: Java does manipulate objects by reference, and all object variables are references.
So when you have Object o1 and Object o2, in fact o1 and o2 are just references to memory spaces that hold the object not the object itself.
When you have o1 == o2 , you are comparing the two references not the objects themselves but if you want to compare them you need to override the equals() method.
Now, let's talk about your case:
Node current = root; this means that current and root are referring to the same object (the same location in memory). So there is only one object and two references.
While playing in Java. I saw different behaviour if an object is modified and given a value and different value if it is assigned a new object. Here is code that I made to show the result.
public class Test {
int i;
public Test(int j) {
this.i = j;
}
public static void main(String[] args) {
Test A = new Test(5);
Test N = new Test(5);
add(A);
makeNew(N);
System.out.println("Value of A.i= "+A.i);
System.out.println("Value of N.i= "+N.i);
}
private static void add(Test t) {
t.i+= 3;
System.out.println("Inside method add() t.i= "+t.i);
}
private static void makeNew(Test t) {
t = new Test(8);
System.out.println("Inside method makeNew() t.i= "+t.i);
}
}
Here is the output of the above code.
Inside method add() t.i= 8
Inside method makeNew() t.i= 8
Value of A.i= 8
Value of N.i= 5
In above example object A is modified to value 8. And object B is given a new object itself. But calling them back only object A shows new value. Object B shows the old value itself. Should not they be showing same value because both case are pass by refernce? I was expecting same value for A.i and N.i.
Here's what happens:
Test A = new Test(5);
Test N = new Test(5);
add(A); // method is add(Test t)
makeNew(N)// method is makeNew(Test t)
t = new Test(8);
System.out.println("Value of A.i= "+A.i);
System.out.println("Value of N.i= "+N.i);
Whenever you make a variable equal to an object and later use new on that object somewhere else like through another reference, your variable you set to the objects reference no longer points to whatever the new object is, but still holds onto the old. So if multiple variables at different scopes hold a reference, they all need a way to have them made equal to whatever the new object is or they no longer are in synch.
I think this will make you doubt clear:
You see N still point to the first object
In your makeNew, you're overwriting the reference to the existing object (that's passed in as the paramter) with your new test(8) object. However, that's local inside makeNew, so the original object sitting inside main(...) is not affected.
Java is pass-by-value. You pass the reference of an object as a value, and you can thus modify that object. However, you cannot modify the actual reference of an object and make it point to something else.
Your question has already been answered here: Is Java "pass-by-reference" or "pass-by-value"?
In Java you do not pass the actual object nor do you pass the reference to the object. You pass copy of the reference to that object. Now when you say
makeNew(N);
N which is the reference to new Test(5) is not passed but the copy of it's reference is passed. In the makeNew() function this copy points to some new object and print the value appropriately but the N will still point to the original object.
class Nodetype
{
int info;
Nodetype next;
Nodetype(int i)
{
info=i;
next=null;
}
}
My textbook has this code to create Linked List dynamically.
The question is, when the programs is executed line-by line, it defines variable 'info' as type 'int' & then variable 'next' as Nodetype.
What is actually happening here?
does it mean that variable 'next' will contain -
Constructor 'Nodetype'
int info
Nodetype "next" where "next" will again have all 1,2,3 & then 3 will again have 1,2,3...and so on....till infinity?
I'm really irritated because I'm unable to understand how it works, can someone easily explain this?
Your code follows very well the definition of list: a list is null or an element followed by a list.
The "element", in your case, is defined by an int value, and the "followed by" part is the next variable; in Java variables (when they are not literals, as int values are) are actually pointers, so while they are not initialized they don't store any valid value and they don't point to any memory area (i.e. their value is null), so while the next variable is kept as-is your element is not followed by any other. To dynamically add elements to your list you need a pointer to the last element you added, otherwise you would not be able to find them again:
int i = 0;
Nodetype head = new Nodetype(i++);
Nodetype last = new Nodetype(i++);
head.next = last;
while (i<5) {
Nodetype temp = new Nodetype(i++);
last.next = temp;
last = temp;
}
while(head) {
System.out.println(head.info);
head = head.next;
}
Notice how, with the last few lines, you lose the head pointer and you have no way to get back the starting point of your list.. Keep that in mind when working with lists ;)
At first variable next doesn't point to any object(it points to null). At some time you will make it point to another node with next = new NodeType(number). The idea is that you use composition - you have one instance of class which has a reference to another instance. It is like nodeA points to nodeB, nodeB points to nodeC. Here you have three instances and the first instance has a reference to the second instance and the second instance has a reference to the third instance. The third instance is the last one and its next instance points to null.
the field next is a reference to an object of type Nodetype. at first it will point to nothing - since it is instantiated to null. when you assign a value to it, it will point to that value only, nothing will continue infinitely unless you create a cycle within the list.
You created class NodeType and inside of the class you defined object of that class. So that object (in your example next) will have int info variable NodeType next object and constructor.
It will contain Null, as the variable is not initialized to any value.
Nodetype is your class that defines the data a node instance will contain as well as the reference to the next node in the linked list. That reference to the next node will be an object of type Nodetype. Nothing too difficult here, this is the classic implementation of a Linked List.
You might want to check out this great linked list resource from Stanford.
The way this works is that the list is made up of single elements, each of which only has a pointer to the one that comes after it:
Nodetype next;
The information each element within the list actually holds is this:
int info;
You can think of a list like a "chain": it's not really a single object, but a compound object of a number of links. From each link, you can only see the next link (or, in case of linked lists that have references in both directions: the next and the previous link), so in order to have all elements available, you will have to keep the reference to the first element in the "chain".
Note: List objects are single objects that have a reference to the first link of the "chain".
next is a reference to another Nodetype instance. If next == null it means the current element is the last one in the list.
Let's see an example:
Nodetype node = new Nodetype(0); // i = 0, next = null
Nodetype anotherNode = new Nodetype(1); // i = 1, next = null
node.next = anotherNode; // now the first node has a ref to the second
#include<stdio.h>
#include<stdlib.h>
void print_list(int *arr,int *size,int *capacity)
{
printf("capacity = %d; size = %d; elements = ",*capacity,*size);
for(int i=0;i<(*size);i++){
printf("%d ",arr[i]);
}
printf("\n");
}
int * push_back(int *arr,int data,int *size,int *capacity)
{
int *b;
if(*size == *capacity){
*capacity = 2*(*capacity);
b = (int *)malloc(sizeof(int)*(*capacity));
for(int i=0;i<(*size);i++){
b[i]= arr[i];
}
b[*size]=data;
*size=*size+1;
print_list(b,size,capacity);
return b;
}
arr[*size]=data;
*size=*size+1;
print_list(arr,size,capacity);
return arr;
}
int main()
{
int size=0;
int n;
int x;
int *arr;
arr = (int *) malloc(sizeof(int));
int capacity=1;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&x);
arr=push_back(arr,x,&size,&capacity);
}
}
its working.