Serializing Java: treat all your fields

All your Java fields belong to us. Reflection is powerful but you have to remember a few rules before dealing with class fields.

This is Serializing Java – emerging series about writing your own serializer in case you didn’t like other serializers.

Don’t let modifiers constrain you

Any private field seems to be not modifiable outside of the owner class. However, it’s as simple as getting a Field  and setting it to be accessible:

Oh, and remember final  fields? Check this out:

Boom! final  is mutable.

Mutable Strings

And so, mutable are strings, too! Probably everyone knows why  equals()  is essential to comparing strings (because comparing references may not work!).

Hey, look mum, that’s soo clever:

Suddenly, you realize that all your String fields were never immutable.

Fields of inner class

Inner class (in Java: non-static class) can be instantiated only in a context of parent class instance.

Too complicated? Let’s have an example:

In this case you can do new Game.GlobalId()  but you can’t new Game.Entity()  outside of Game class. Thanks to that,  Entity  has access to all fields of parent Game  object while GlobalId  doesn’t have that connection.

Then there’s the thing – through Reflection we could call getDeclaredFields()  for both Entity  and GlobalId  classes. You’d expect to get 2 fields per class. However, Entity  has these fields:

  • id
  • name
  • this$0

What? Let’s filter that (let’s give some Kotlin here):

Seems simple. But. Noticed that zero at the end of this$0 ? Do you expect to see this$1 ? Yes! The trailing number depends on how deep the inner class is and to which  this  would refer.

Let’s fix that:

Summary

Often there is more trouble and possibilites than you expect. Thus, behold the dychotomy of power and lack of full determinism – that’s in terms of available Reflection power and implicit in-memory dependencies.

References