50% developed

Accessing Private Features with Reflection

From Wikibooks, open books for an open world
Jump to navigation Jump to search

Navigate Reflection topic: v  d  e )

All features of a class can be obtained via reflection, including access to private methods & variables. But not always see [1]. Let us look at the following example:

Computer code Code listing 10.3: Secret.java
public class Secret {
  private String secretCode = "It's a secret";
 
  private String getSecretCode() {
    return secretCode;     
  }
}

Although the field and method are marked private, the following class shows that it is possible to access the private features of a class:

Computer code Code listing 10.4: Hacker.java
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
public class Hacker {
 
   private static final Object[] EMPTY = {};
 
   public void reflect() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
     Secret instance = new Secret();
     Class<?> secretClass = instance.getClass();
 
     // Print all the method names & execution result
     Method methods[] = secretClass.getDeclaredMethods();
     System.out.println("Access all the methods");
     for (Method method : methods) {
        System.out.println("Method Name: " + method.getName());
        System.out.println("Return type: " + method.getReturnType());
        method.setAccessible(true);
        System.out.println(method.invoke(instance, EMPTY) + "\n");
     }
 
     // Print all the field names & values
     Field fields[] = secretClass.getDeclaredFields();
     System.out.println("Access all the fields");
     for (Field field : fields) {
        System.out.println("Field Name: " + field.getName());
        field.setAccessible(true);
        System.out.println(field.get(instance) + "\n");
     }
  }
 
  public static void main(String[] args) {
    Hacker newHacker = new Hacker();
 
    try {
      newHacker.reflect();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
Standard input or output Console for Code listing 10.4
Access all the methods
Method Name: getSecretCode
Return type: class java.lang.String
It's a secret
Access all the fields
Field Name: secretCode
It's a secret
Clipboard

To do:
We need to add some explanation of what is going on here.


JUnit - Test Private methods[edit | edit source]

JUnit's are unit test cases, used to test the Java programs. Now you know how to test a private method using Reflection in JUnit. There's a long-standing debate on whether testing private members is a good habit[1];There are cases where you want to make sure a class exhibited the right behavior while not making the fields that need checking to assert that public (as it's generally considered bad practice to create accessors to a class just for the sake of a unit test). There are also cases when you can greatly simplify a test case by using reflection to test all smaller private methods (and their various branches), then test the main function. With dp4j[dead link] it is possible to test private members without directly using the Reflection API but simply accessing them as if they were accessible from the testing method; dp4j injects the needed Reflection code at compile-time[2].

  1. What's the best way of unit testing private methods?, March 7, 2011
  2. Reflection API injected at compile-time [dead link]


Clipboard

To do:
Add some exercises like the ones in Variables