DEV Community

George Marr
George Marr

Posted on

Reflection, why it's so useful.

So it's likely at some point you've heard the term "Reflection" used in programming, I was surprised that quite a few of my developer friends had heard of this term but never knew what it was or how to do it. And in short, it is incredibly useful to know.

What is it?

Reflection is the process of taking an API, Library or a standard library and inspecting it, looking into fields, interfaces, classes, methods (etc) at runtime. It also makes it possible to create new objects and invoke fields.

For example, lets say we have a class in Java called Shopping list, and when we call the functions from this class all we can see is this

import io.gpm.ShoppingList;

public void printList() {
     ShoppingList.getEverything();
}

Now from that example, you can easily tell what it would the method getEverything(); would be doing, however, what if we couldn't see the actual code behind it and we wanted to include something of our own? This is where reflection comes into play.

How

In all languages it is going to be different for this example I'll be demonstrating it in Java, thankfully Java comes packed with everything required to handle reflection. This may not be the same with other languages, from research it looks like the majority of widely used languages come with some form of support.

Below are some very basic examples of how we can obtain information on Methods and classes.

Method[] methods = ShoppingList.class.getMethods();

for(Method method : methods) { System.out.println(method.getName()); }
Class shoppingListClass = ShoppingList.class;

A lot more examples can be found at Oracles official documentation on Reflection

Why would we need this?

Well a perfect example of why we may need this is Minecraft, one of the most popular games in the world. The large majority of it's online servers run off a API named SpigotMC however because the API and the game only gives us a limited amount of methods and abilities to do things with we need to reflect into the API and into the client to give us access to the packets it sends out and the current methods, from there it can be modified to do so much more but still limited. Example of this here

  private static void send(Player player, PacketPlayOutTitle.EnumTitleAction action, String message, int fadeIn, int stay, int fadeOut) {
        PacketPlayOutTitle packetPlayOutTitle = new PacketPlayOutTitle();
        titleClass.getField("a").set(packetPlayOutTitle, action);
        if (action == PacketPlayOutTitle.EnumTitleAction.TITLE || action == PacketPlayOutTitle.EnumTitleAction.SUBTITLE) {
            titleClass.getField("b").set(packetPlayOutTitle, compone(message));
        }
        titleClass.getField("c").set(packetPlayOutTitle, fadeIn);
        titleClass.getField("d").set(packetPlayOutTitle, stay);
        titleClass.getField("e").set(packetPlayOutTitle, fadeOut);

        if (player != null) {
            ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packetPlayOutTitle);
        } else {
            throw new IllegalArgumentException("Provided player was null!");
        }
    }

As you can see we had to investigate the API a bit to find some hidden fields with weird names and then replicate the function ourselves to actually get this working. In the end, it just displayed some text on the screen.

This is just a small example of how useful Reflection can be, below are some examples and documentation for Reflection on other languages

Java
JavaScript
Ruby
PHP (Referred to as Metaprogramming)
Python

Discussion (3)

Collapse
chains5000 profile image
Pablo Fradua

The problem with that Minecraft code is that it won't work if/when they make changes to those non public API methods. You won't be able to upgrade to a new API version without lots of changes.

Collapse
rapidnerd profile image
George Marr Author

Agreed, however, there's a work around this. When the game update the client sends a version packet meaning we can adjust the methods to the newer ones or older ones depending on the client version.

Collapse
chains5000 profile image
Pablo Fradua

Still, that's a potential risk for your project. One thing's having a dependency on a library and another's depending on methods the API provider hasn't made public.
Also, there might be a reason why those methods are not supposed to be used.