views:

1114

answers:

12

I have a constructor like as follows:

public Agent(){

 this.name = "John";
 this.id = 9;
 this.setTopWorldAgent(this, "Top_World_Agent", true);

}

I'm getting a null pointer exception here in the method call. It appears to be because I'm using 'this' as an argument in the setTopWorldAgent method. By removing this method call everything appears fine. Why does this happen? Has anyone else experienced this?

A: 

this is not null, that much is sure. It's been allocated.

That said, there's no need to pass this into the method, it's automatically available in all instance methods. If the method's static, you may want refactor it into an instance method.

sblundy
+7  A: 

You can pass this to methods, but setTopWorldAgent() cannot be abstract. You can't make a virtual call in the constructor.

In the constructor of an object, you can call methods defined in that object or base classes, but you cannot expect to call something that will be provided by a derived class, because parts of the derived class are not constructed yet. I would have expected some kind of compiler error if setTopWorldAgent() was abstract.

In Java, you can get surprising behavior with the contructor and derived classes -- here is an example

http://en.wikipedia.org/wiki/Virtual_functions#Java_3

If you are used to C# or C++, you might think it's safe to call virtual functions and not be calling overridden ones. In Java, the virtual call is made even though the derived class is not fully constructed.

If this isn't what's happening, then presumably, all of the parts of this that setTopWorldAgent() needs are initialized -- if not, it's probably one of the members of this that needs to be initialized.

Edit: thought this was C#

Lou Franco
But even if you do the function call *won't* fail!
Konrad Rudolph
This answer is clearly incorrect. Even if the class was abstract and the method setTopWorldAgent was also abstract the creation at this point would have this as not being null. It is easily shown with a testcase.
PintSizedCat
Damn, why are you people downvoting this answer? It's correct!
Konrad Rudolph
In Java, you can call an abstract method and it will be resolved to the implementing method in the sub-class. But you are correct that sub-class variables will not have been initialed. Parent class constructor are called before child.
sblundy
Thanks Konrad!this is not null -- something else is. I was suggesting things that might be null or ways in which you could get fooled into thinking something was called when it wasn't.
Lou Franco
@Konrad Rudolph Because in contains erroneous information about Java. You can call abstract methods from a constructor
sblundy
Can you edit your answer so that it's clearer, you can clearly call abstract methods from constructors. This is not null but I admit that (as sblundy says) subclass variables on this may be null.
PintSizedCat
ahh -- thought this was C# -- will correct
Lou Franco
Yes -- I edited the answer for Java, and provided a link to an example that I think is close to what's happening here.
Lou Franco
@sblundy: Damn. The question was originally tagged C#, not Java. But anyway, the answer even then contained clarification that made the answer absolutely correct.
Konrad Rudolph
@Konrad Rudolph: The original post had neither tag. I just checked the history and it seems v2 was retagged c#, then the owner changed that to Java. In the original post the only clue it was java was that setTopWorldAgent wasn't SetTopWorldAgent. But we're all straight now, so I changed my vote.
sblundy
A: 

"this" should never be null. Are you sure that the exception is being thrown because of that?

Something to beware of is that if the method is virtual, or calls any virtual methods, then a method belonging to a subclass might be run before the subclass's variables are initialised.

Khoth
In Java, you can call abstract methods in a constructor. The implementing method in the subclass will be called.
sblundy
A: 

The error must be somewhere else because the above code definitely works, the null reference must be something else.

Konrad Rudolph
+1  A: 

Why would setTopWorldAgent need this as an argument? Based on the invocation, it's an instance method, so it could reference this without needing to receive it as a parameter.

Hank Gay
+1  A: 

I think more to the point, why on earth are you passing 'this' as a parameter to a method in 'this'?

The following would test what you say is happening to you and I have no troubles with it.

public class Test {
  public Test() {
    this.hi(this);
  }
  public void hi(Test t) {
    System.out.println(t);
  }

  public static void main(String[] args) throws Exception {
    Test t = new Test();
  }
}
PintSizedCat
A: 

Given that setTopWorldAgent appears to be an instance method, why are you passing through this to it anyway?

+4  A: 

Out of curiousity, why are you passing 'this' to a member function of the same class? setTopWorldAgent() can use 'this' directly. It doesn't look like your constructor or setTopWorldAgent() are static, so I'm not sure why you would pass a member function something it already has access to.

Unless I'm missing something...

unforgiven3
A: 

If your Agent is implementing ITopWorldAgent then you should actually do this:


Agent agent = new Agent("John", 9);
agent.setTopWorldAgent(agent, "Top_World_Agent", true);

If not, then why you are setting something in the manner you are?

I presume that something in the setTopWorldAgent method is using a value that hasn't been initialised yet in your constructor.

JeeBee
A: 

Cheers everyone, parts of setTopWorldAgent() needed initializing.

Wow. Sorry, but the information content of the question was extremely poor and as a consequence, all answers were pure guesswork.
Konrad Rudolph
A: 

The rules of Java state that you should never pass 'this' to another method from its constructor, for the simple reason that the object has not been fully constructed. The object it references may be in an inconsistent state. I'm surprised that the actual 'this' reference is null, but not at all surprised that some member of 'this' is null when it is passed to setTopWorldAgent, and that the method is throwing the exception because of this.

Usually you can get away with passing 'this' from constructors as long as you don't actually access any members or call methods for example if you want to set a reference to 'this' in another object.

In this case of course the argument is unnecessary as the method already has a reference to 'this'.

DJClayworth
A: 

Glad you got to an answer. I'd like to add that passing 'this' as a parameter can lead to unexpected concurrency issues. You basically are providing the possibility of the state of the object to be unsafely manipulated by potentially non-thread safe code.

Dennis S