aspose file tools*
The moose likes I/O and Streams and the fly likes Externalizable and null values in read/writeExternal Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » I/O and Streams
Bookmark "Externalizable and null values in read/writeExternal" Watch "Externalizable and null values in read/writeExternal" New topic
Author

Externalizable and null values in read/writeExternal

Leslie Chaim
Ranch Hand

Joined: May 22, 2002
Posts: 336
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


Normal is in the eye of the beholder
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
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 ]

"I'm not back." - Bill Harding, Twister
Leslie Chaim
Ranch Hand

Joined: May 22, 2002
Posts: 336
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

Joined: Jan 30, 2000
Posts: 18671
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

Joined: May 22, 2002
Posts: 336
Just keep on rambling while I will learn on your account
Many Thanks!
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Externalizable and null values in read/writeExternal