Impossible null pointer
I have a real weird problem. (Very important note: this is an ex开发者_开发百科ample cause I can't paste the original code, I wrote it as text with no compiler.) I have 2 classes:
class B {
private int num = 9;
public int getNum(){
return num;
}
public void setNum(int num){
this.num = num;
}
}
class A {
private B b = new B();
public void setB(B b){
b.setNum(b != null? b.getNum() : 8);
}
public B getB(){
if (b == null)
System.out.println("How possible?");
return b;
}
}
Now, sometimes I get the print... but I don't see how's that possible.
A is a serialized class, but yet I can't figure it out.
It's not possible, no. You'll get a type error in the definition of A.getB()
when you try to compile it, and your definition of A.setB()
looks dubious as well (shadows b
).
There are a few circumstances in which b
might be null:
- reflection.
b
might be set to null reflectively, which circumvents your setter. - custom serialisation.
b
might be explicitly restored as null. Alternatively, ifB
is not serialisable, you have it marked as transient to avoid errors and it's not restored.
To verify a simple serialisation workflow, use the following code:
Object object = "someString";
ByteArrayOutputStream holder = new ByteArrayOutputStream();
new ObjectOutputStream(holder).writeObject(object);
Object readObject = new ObjectInputStream(new ByteArrayInputStream(holder.toByteArray())).readObject();
System.out.println(readObject);
where the first line is replaced by the actual object you wish to test
If you manage to serialize an instance of A
which has b == null
, then you get a NPE. The reason is that during de-serialization, the constructor isn't invoked and therefore, private B b = new B();
isn't run, so b
stays null
.
Did you serialize the instance of A before adding the initialization of B to the class?
If that is the case you could get an instance of A where b is null because the constructors are not called (initializing a member of the class is part of the implicit constructor).
Then you will need to add an implementation of readObject() to class A there you can check whether or not b is null and initialize it if necessary.
This line won't compile either:
b.setNum(b != null? b.getNum : new B());
Well, what about this? If you give B as a parameter, why not use it?
class A {
private B b = new B();
public void setB(B b){
if(b != null) {
this.b = b;
}
}
public B getB(){
return b;
}
}
Just an idea: replace
System.out.println("How possible?");
with
new Exception().printStackTrace();
That should make it easier for you to see what happened just before. Otherwise, without more information, the only things that seems a possible cause is the serialization.
精彩评论