Peeking behind the forbidden door of Reflection

You shouldn’t be reading this one!

Prafull Mishra
ProAndroidDev

--

Cover image for opening the forbidden door of reflection
Newly inspired illustration style | by Prafull Mishra

Pssst…hey you. Yes, you. The one reading this. Before you go any further, know that this read will change your perception towards programming languages. You will see how all the “rules” you have learned so far, are merely a smoke screen. Just a simulation your code is confined in, when in reality things are much more sophisticated, while also being flexible enough to change your perception. 👻

Ready? Let’s do this!

The Backstory 💭

Alright, fine. The official doc of Reflection API goes like this:

`This is a relatively advanced feature and should be used only by developers who have a strong grasp of the fundamentals of the language’

and the following line one ups the above one:

`..can enable applications to perform operations which would otherwise be impossible’

Mysterious! Right?

What adds to this is that I have read/heard the word Reflection here and there around many popular libraries such as Dagger(v1) and GSON. But at the same time, never really saw any Reflection related article pop-up in my recommendations, like ever.

This combination piqued me, and hence lead me to nose-dive right into it. And now I want to share my findings with you too. So let’s get started!

Reflection — What & Why? 🙇

While I still haven’t come to terms with the name Reflection, if I were to describe it in a more layman terms, I would describe it as an introspection tool for your existing code.

Reflection allows us to view & change the runtime state of our code.

If you have ever used Jetbrains IDE/Android Studio’s Debugger, you must have observed that you can inspect values of all the members of an object instance, even the private ones!

Android Studio Debugger sample screenshot showing values of all class members while debugging, best Reflection use case
Android Studio debugger is capable of showing values of all members, even private ones

But how is this possible? Its rule 101, that private members cannot be accessed directly and if your IDE is also playing by the rules, then it shouldn’t be possible?

I always used to think that it might be that there is backdoor for special purpose access that is allowed to be used strictly by these “trusted first class citizens”. This backdoor is basically Reflection. Hence we can say that with Reflection, code can be accessed as a data source, which can be read and modified at runtime. These elevated privileges of Reflection is what makes it a God-like entity enabling it to achieve feats that normal code just can’t.

Demo time 💥

Now that we know, what Reflection is and seen its application, let’s try our hands on to break the matrix with this newly discovered super power! Also, while I have mentioned code snippets below, do try it side by side on your own machine as well, to experience it first hand!

While Reflection exists in both Java and Kotlin, we will be seeing samples written in Kotlin (to be more in context with modern Android development).

Reflection meme, based on Thor Ragnarok’s Hammer shattering scene
Had to make this one!

1. Accessing private members 😵

This basically shatters the “normal” perception we have towards code. Sure all books and tutorials told us that private fields of a class cannot be accessed by other external classes, but, not today. Let’s break this rule!

And just like that, we were able to print the value of a private field.

2. Enumerating Class methods 👮

Just like we did with fields, all members of a class can be enumerated, regardless of whether they are private or not:

and the output looks like:

Our custom methods show up, irrespective of their visibility scope

Note: the output includes not only the private and non-private methods we declared, but it also shows the universally available methods — equals , hashCode & toString .

Here too we can change the visibility of private methods to public (if required) by setting the isAccessible property of the method to true.

3. Accessing Class constructors 🐤

Now imagine that you have a task of building a Dagger like DI library, what is the first step you need? You will need to determine the parameters required for all the available Class constructors. So again, Reflection can help us here:

And as output we get list of parameters of all declared constructors in that class, along with their return type, which of course is the class itself (ie. Contact). Have a look:

Package names omitted for brevity.

The Caveats 🚨

Now obviously nothing comes without its downsides. Unfortunately, Reflection has its own set of limitations, including but not limited to:

  • Reflection based code has slower performance compared to their non-Reflection based counterparts
  • Reflection requires a runtime permission which may not be present under certain Security managers
  • Reflection can result in unexpected side-effects, considering that it allows for illegal operations
  • Certain language features are not present in Reflection such as compile-time type resolution

Conclusion 🏁

We barely scratched the surface of Reflection APIs and saw how it can make our code operate in a non-traditional manner. It is a powerful tool, and is made for use-cases when there is a requirement to examine or modify the runtime behavior of JVM applications. While it allows us to get out of the code system, indiscriminate use of Reflection can not only cause significant performance overhead, but can also cause inconsistencies in your code’s working.

Personally, I can’t recall any case where I wished for something like this to exist, but now that I know, I might find one someday!

Further read 📖

To read more about how Reflection works in Java & Kotlin in detail, I encourage you to take out few minutes to read more on these topics through the following sources:

Curious to know what all use-cases you aim to solve via Reflection, let me know in the comments. I hope you all learned something new today! Do give some claps, if so 👏 👏

Use this power responsibly. Until then, peace out! ✌️

--

--