Showing Posts From

Reflection api

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; }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());}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; } }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());}