DEV Community

Shubham Kumar
Shubham Kumar

Posted on • Originally published at blog.shubham.codes on

Reflection API in Java

Where is this used?

This is used to analyze/modify the behaviour of a class at runtime. Using this, you can view or change the private/public fields at wish (without exposing any getter/setter). Personally, I have used this in one of our projects at GreyOrange to write unit test cases. Using this in main code is a big no-no as it exposed you critical fields to the world.

Main Class

Let’s create a main class for which we will write some test cases. But we want to test some private fields for which we don’t have a direct getter. The idea is to use reflection api to access such fields and fetch their current value or modify them if required.

Here is a Duck class which has 3 fields of which 1 is static. Each time a duck class is created count which is the static field is increased by one. Each duck has an associated name and age.

public class Duck {
    private String name;
    private int age;
    private static int count = 0;

    public Duck(String name, int age) {
        this.name = name;
        this.age = age;
        count++;
    }

    public static boolean canCreateMoreDucks() {
        return count < 10;
    }

    public String getName() {
        return name;
    }

    public boolean canDrinkAlcohol() {
        return age >= 18;
    }
Enter fullscreen mode Exit fullscreen mode

Test Class – uses reflection API

Change the value of a private field inside a class

Field and getDeclaredField are used to access a variable. Using setAccessible as true will expose any private fields which can be manipulated.

@Test
public void testDuckCanDrinkAlcohol() {
    Duck duck = new Duck("Donald", 5);
    assertEquals("Donald", duck.getName());
    assertFalse(duck.canDrinkAlcohol());

    // change age and check if duck can drink alcohol
    // But I don't want to create a setter for this
    // Use reflection API to change the age
    try {
        Class<Duck> duckClass = Duck.class;
        Field ageField = duckClass.getDeclaredField("age");
        ageField.setAccessible(true);
        ageField.setInt(duck, 20);
    }
    catch (Exception e) {
        e.printStackTrace();
        assert false;
    }

    assertTrue(duck.canDrinkAlcohol());

}
Enter fullscreen mode Exit fullscreen mode

Get the value of a static private variable in a class

A static field can be accessed in the similar way.

@Test
public void testDuckCanCreateMoreDucks() {
    // Instead of creating more ducks
    // I will use reflection API to change the count
    Duck duck = new Duck("Donald", 5);
    assertTrue(Duck.canCreateMoreDucks());

    // Also assert count was 1
    // But I don't want to create a getter for this
    try {
        Class<Duck> duckClass = Duck.class;
        Field countField = duckClass.getDeclaredField("count");
        countField.setAccessible(true);

        // Don't need to pass an instance as count is static
        Object countObject = countField.get(null);
        int count = (int) countObject;
        assertEquals(1, count);
    }
    catch (Exception e) {
        e.printStackTrace();
        assert false;
    }
}
Enter fullscreen mode Exit fullscreen mode

Change the value of a static private variable in a class

You can use setInt to change the value of the Field.

@Test
public void testDuckCannotCreateMoreDucks() {
    // Instead of creating more ducks
    // I will use reflection API to change the count
    Duck duck = new Duck("Donald", 5);

    // change count to 10
    try {
        Class<Duck> duckClass = Duck.class;
        Field countField = duckClass.getDeclaredField("count");
        countField.setAccessible(true);
        countField.setInt(null, 10);
    }
    catch (Exception e) {
        e.printStackTrace();
        assert false;
    }

    assertFalse(Duck.canCreateMoreDucks());

}
Enter fullscreen mode Exit fullscreen mode

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay