Win a copy of Design for the Mind this week in the Design forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Externalizable and null values in read/writeExternal

 
Leslie Chaim
Ranch Hand
Posts: 336
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For performance purposes I chose to implement Externalizable but I am running into null pointer exceptions if any of my members are null.
Originally, I wrote this helper:

I used the above to read/write my String data members within my read/writeExternal methods and it works fine. The problem is with the Object type - some members of my class are objects and they can be null (at times).
I am wondering if I can modify the above code to deal with Objects and read/write the String data members?
In general, is there a more elegant way to handle the state of null values?
Thanks,
Leslie
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
From my own testing, it seems as though writeObject() and readObject() handle nulls just fine, though writeUTF() and readUTF() do not. If I write an object containing a null field, that seems to be no problem either. So I'm probably doing something different from you, Leslie. Could you show some code in which writeObject() throws a NullPointerException? My own tests are attached below.
Regradless, it's a bit vexing that the API never says anything about whether nulls are allowed or not, for either writeObject() or writeUTF(). So I suppose the proper response is to assume that an implementation may throw NullPointerException (true for writeUTF() at least) and code around that limitation. Your code using writeBoolean() and readBoolean() looks like a perfectly reasonable and effective approach to this, and the same sort of thing could be done for writeObject() and readObject(). Even if thus far I can't replicate your problem, the weakness in the API is a cause for concern.

And sample test code attempting to replicate LC's problem:

[ October 09, 2003: Message edited by: Jim Yingst ]
 
Leslie Chaim
Ranch Hand
Posts: 336
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
From my own testing ... Blah blah Hey Jim that's all I need, your testing
I only experienced problems with read/writeUTF and not with writeObject and to be totally hunst the Object members for my class can never be null. I will take note of your test for future references
In any case, I can see that this area is a bit murky and we need some arm twisting. I guess we can call it creativity
Another solution for this problem is to simply make sure that you String(s) are never null.
What I did in the constructor was this:

Which leads me to another (simple) question:
Given the above, the setXXX methods of the class should also have the same approach. Thinking in the constructor is it better to leave the code as is or call it's setXXX method as in:

Thanks so much for your help, Jim
[ October 09, 2003: Message edited by: Leslie Chaim ]
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I can see that this area is a bit murky
Yeah, I'd probably be willing to assume that writeObject() and readObject() will always handle null OK; they just aren't fully documented in that respect.
For your other questions - I'm a bit hesitant to have a setXXX() method that accepts null and then sets XXX to some other value, as that seems counterintuitive to me. You can document the extra behavior here, but I think it's unwise to go against the standard behavior for set methods. I'd prefer to simply throw NullPointerException if the argument is null (IllegalArgumentException would also be valid). Replacing null with something else has a good chance of hiding an error, IMO; I'd rather discover the error right away.
How about something like:

As for assigning the variables from the constructor: I often do stuff like that if I want to communicate to users that they aren't supposed to instantiate the class without providing a value for that field. The user may or may not call a set method later on; if I want to ensure the field has a value, the simplest method is often to force a value to be provided in the constructor. In many cases I won't even provide other constructors, or a set method - you've got to put the correct value in the constructor.

This makes the most sense if the field in question is (or can be made) final, as shown.
The weakness of this approach is that in can be a bit confining for the user, and can also be less readable. When a reader sees "new Foo(100, 200, bar)" it's not necessarily obvious what role x, y, and bar have. But if they see

That's probably more readable. (Though of course, more typing.) It's a matter of which style you wish to encourage. The more parameters there are in a constructor, the more I'd be inclined to favor getting rid of the contructor; it's hard for readers to keep a long list of params straight.
OK, enough rambling for now. Cheers...
 
Leslie Chaim
Ranch Hand
Posts: 336
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just keep on rambling while I will learn on your account
Many Thanks!
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic