Java/Maven

Accessing Java Private Attributes and Methods

Java reflection is a very powerful framework.

Sometimes its power seems outside the usual Java methodology.

For example, I needed to manually change a private variable in one of the classes I was testing.

Java reflection has an API that allows this. Of course, the API does not know if one is in a test or production source code. It works anywhere!

Below is an example of three classes.

  • IntWrapper is the class under question.
  • IntWrapperTest is the JUnit class
  • RegularMainClass is a class with a main method, almost a copy of IntWrapperTest.

It is worth noting that the testers and the testee are in separate packages. So one can change the private variable or call a private method of any class in any package!

package com.otherexample;

public class IntWrapper {

	private int i;
	
	public IntWrapper(int i) {
		this.i = i;
	}

	private void incrementI() {
		i++;
	}
	
	public int getI() {
		return i;
	}
	
}
package com.example;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.junit.Test;

import com.otherexample.IntWrapper;

import static org.junit.Assert.*;

public class IntWrapperTest {

	@Test
	public void testPrivateMembers() {
		try {
			IntWrapper iw = new IntWrapper( 15 );
			assertEquals(15, iw.getI() );
			Field f = iw.getClass().getDeclaredField("i");
		
			f.setAccessible(true);
			f.setInt(iw, 18);
			assertEquals(18, iw.getI() );
			
			Method m = iw.getClass().getDeclaredMethod("incrementI");
			m.setAccessible(true);
			m.invoke(iw);
			assertEquals(19, iw.getI() );
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}
	
}
package com.example;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.otherexample.IntWrapper;


public class RegularMainClass {

	public static void main(String[] args) {
		try {
			IntWrapper iw = new IntWrapper( 15 );
			if( 15 != iw.getI() ) System.err.println("Assertion failed");
			else System.out.println("all is well 1");
			Field f = iw.getClass().getDeclaredField("i");
		
			f.setAccessible(true);
			f.setInt(iw, 18);
			if( 18 != iw.getI() ) System.err.println("Assertion failed");
			else System.out.println("all is well 2");
			
			Method m = iw.getClass().getDeclaredMethod("incrementI");
			m.setAccessible(true);
			m.invoke(iw);
			if( 19 != iw.getI() ) System.err.println("Assertion failed");
			else System.out.println("all is well 3");

		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}

}
Standard