object becomes null on return

H

HalcyonWild

Hi,

I am facing a strange problem and I cannot find the reason. I have a
calling method, processOrder() in a plain java file in which I am doing
this.

public Order processOrder()
{
Customer c = null;
if (orderType.equals("typeA")
{
processA(c, orderManager);
}
else if (orderType.equals("typeB")
{
processB(c, orderManager);
}

logger.log("customer is "+c);
//this prints null. though i populate it in process methods.

}

private void processB(Customer c, OrderManager orderMgr)
{
-- some lines --
c = CustomerBean.getCustomerByID(orderMgr.getCustomerId());
//this is a session Bean.

logger.log("customer in process method = "+c); //prints fine

}

I wonder what am I doing wrong. How can c become null in the calling
method. I am getting a nullpointer exception for sub. Am I missing
something very fundamental. Or is it some strange behaviour of session
beans. References are passed for objects in Java. So c should retain
its value. I have come across very similar situations and this has
worked for me. I checked if I am making c = null anywhere, but that is
not the case. Also the logs show c just before return in called method.
And immediately, I log c in the calling method, which shows null. This
happens for both processA and processB methods, and they are similar,
with some extra processing for processA.

Thanks,
Halcyon
 
I

Ingo R. Homann

Hi,

What you explain, is not strange, it is simply the behaviour Java uses
when passing parameters. (If you like it or not, that is another
question! ;-)

Parameters in Java are not "inout parameters". The reference (=pointer)
to an object is copied when passed to a method.

You can use a return parameter:

public Order processOrder()
{
Customer c = null;
if (orderType.equals("typeA")
{
c=processA(c, orderManager);
}
else if (orderType.equals("typeB")
{
c=processB(c, orderManager);
}

logger.log("customer is "+c);
//this prints null. though i populate it in process methods.

}

private Customer processB(Customer c, OrderManager orderMgr)
{
-- some lines --
c = CustomerBean.getCustomerByID(orderMgr.getCustomerId());
//this is a session Bean.

logger.log("customer in process method = "+c); //prints fine
return c;
}

Ciao,
Ingo
 
M

Michal Waclawek

Hello there.
I think your problem is this: Costumer is always null becose you never give
it a value in this method. Try something like this:


.....else if (orderType.equals("typeB")
{
c = processB(orderManager);
}


private Costumer processB(OrderManager orderMgr)
return CustomerBean.getCustomerByID(orderMgr.getCustomerId));
.....

Sorry for poor English :/
 
H

HalcyonWild

Parameters in Java are not "inout parameters". The reference (=pointer)
to an object is copied when passed to a method.

Thanks Ingo!!
I now realized what I was doing wrong. Basically, it is not possible to
get the object back in the calling method if you are making a new
object in the called method.
In case you are not making a new object and just modifying what you
received as parameter in the called method, the modifications will be
seen in the calling method.
I just tried out the below sample program. I tried out commenting and
uncommenting w=new Vector() line.

import java.util.*;
public class sample2 {
public void modVector() {
Vector v = new Vector();
//Vector v = null;
addVector(v);
System.out.println("Vector vals in calling method\n"+v);
}
public void addVector(Vector w) {
//w = new Vector();
w.add("xyz");
System.out.println("Vector vals in called method\n"+w);
}
public static void main(String args[])
{
sample2 s = new sample2();
s.modVector();
}
};

Thanks all.
Halcyon.
 
T

Timbo

Another possible solution is to have something like a Holder
class, that simulates a pointer. It has an instance variable that
is used to hold the return value:

public class Holder<E>
{
private E value_ = null;

public Holder() {}
public E getValue() { return value_; }
public void setValue(E value) { value_ = value; }
}

So, you can use it like this:

public static void setInteger(Holder<Integer> h)
{
h.setValue(new Integer(5));
}

public static void main(String [] args)
{
Holder<Integer> h = new Holder<Integer>();
setInteger(h);
System.out.println("value = " + h.getValue());
}
 
H

HalcyonWild

Michal said:
I think your problem is this: Costumer is always null becose you never give
it a value in this method. Try something like this:


....else if (orderType.equals("typeB")
{
c = processB(orderManager);
}

hi Michal,
The solution that you gave is right. I wanted it to be void return
type, but thats ok. The reason for failure is not that I never give it
a value. The reason is that, I am reassigning c in below method. I must
not do that. In fact see the sample vector program I sent. If you make
new Vector and pass it as method argument, and just add elements in it,
it will reflect in calling method. if you reassign it, it is lost. This
is because references to objects themselves are copied and not passed
by reference.
Maybe you mean to say the same thing. :)
Thanks.
 
V

Vova Reznik

Roedy said:
You can't possibly modify a local variable by calling a method, unless
you return a value and put it in the variable. In your methods you
are modifying a copy of c not c itself. Java calls by VALUE not by
REFERENCE.

You can possibly modify a local variable by calling a method
if local variable is initiated:
private void doWork(){
Rectangle r = new Rectangle(1, 2, 3, 4);
System.out.println(r);
changeVariable(r);
System.out.println(r);
}

private void changeVariable(Rectangle r){
r.x++;
r.y++;
r.width++;
r.height++;
}
 
R

Roedy Green

You can possibly modify a local variable by calling a method
if local variable is initiated:
private void doWork(){
Rectangle r = new Rectangle(1, 2, 3, 4);
System.out.println(r);
changeVariable(r);
System.out.println(r);
}

private void changeVariable(Rectangle r){
r.x++;
r.y++;
r.width++;
r.height++;
}

you are not changing the value of r. You are changing the fields in
the object r points to.
 
M

Monique Y. Mudama

You can possibly modify a local variable by calling a method
if local variable is initiated:
private void doWork(){
Rectangle r = new Rectangle(1, 2, 3, 4);
System.out.println(r);
changeVariable(r);
System.out.println(r);
}

private void changeVariable(Rectangle r){
r.x++;
r.y++;
r.width++;
r.height++;
}

No, Roedy is technically right. r in your example is a reference.
The method doesn't modify r, which continues to reference the same
object; the method modifies the object r points to.

Changing r would be assigning it a new object, or making it null.

But I'm really tired, so I may be talking out my other orifice.
 
V

Vova Reznik

Monique said:
No, Roedy is technically right. r in your example is a reference.
The method doesn't modify r, which continues to reference the same
object; the method modifies the object r points to.

Changing r would be assigning it a new object, or making it null.

But I'm really tired, so I may be talking out my other orifice.

Yes, method doesn't reassign reference, but may change its members.
 
R

Roedy Green

Yes, method doesn't reassign reference, but may change its members.

It is a fine point. You can't change the reference. You can only
change the fields in the object to which it points. Strictly speaking
the members belong to the object, not the reference.

Using a physical world analogy, there is a strong distinction between
your ability to change my address book, and your ability to break into
the houses it references.

When java calls a method, it is like a person giving an address from
his address book. He does not surrender the book.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top