Mastering Java Reflection: Access and Modify Private Fields with PriUtil

This article explains how to bypass Java's private access restrictions using reflection, introduces the core Field and setAccessible APIs, provides a reusable PriUtil wrapper with get/set methods for instance and static members, and demonstrates usage through concrete test classes and scripts.

FunTester
FunTester
FunTester
Mastering Java Reflection: Access and Modify Private Fields with PriUtil

Why Use Reflection for Private Members

In Java the private modifier hides fields and methods from external code. When working with third‑party libraries or JDK utilities it is often necessary to read or modify such members without changing the original source. Java reflection provides a way to bypass the access checks at runtime.

Core Reflection API

The class java.lang.reflect.Field together with java.lang.reflect.AccessibleObject#setAccessible(true) allows a program to access both instance and static fields regardless of their declared visibility. The same mechanism works for java.lang.reflect.Method to invoke private methods.

Reusable Wrapper – PriUtil

The following utility class encapsulates the repetitive reflection steps. It provides generic methods for getting, setting and invoking private instance or static members. All reflective operations set setAccessible(true) and wrap checked exceptions in a custom FailException to keep client code concise.

package com.funtester.utils;

import com.funtester.base.exception.FailException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * Utility for accessing private members, also works with final fields.
 */
class PriUtil {
    /** Get the value of a private instance field */
    static <F> F get(Object instance, String name, Class<F> type) {
        try {
            Field field = instance.getClass().getDeclaredField(name);
            field.setAccessible(true);
            return type.cast(field.get(instance));
        } catch (NoSuchFieldException | IllegalAccessException e) {
            FailException.fail("Failed to get private field " + name + " from " + instance + ": " + e.getMessage());
            return null; // unreachable because fail() throws
        }
    }

    /** Set the value of a private instance field */
    static void set(Object instance, String name, Object value) throws NoSuchFieldException, IllegalAccessException {
        Field field = instance.getClass().getDeclaredField(name);
        field.setAccessible(true);
        field.set(instance, value);
    }

    /** Invoke a private instance method */
    static <R> R call(Object instance, String name, Class<R> returnType, Class[] paramTypes, Object[] args) throws Exception {
        Method method = instance.getClass().getDeclaredMethod(name, paramTypes);
        method.setAccessible(true);
        return returnType.cast(method.invoke(instance, args));
    }

    /** Get the value of a private static field */
    static <F> F get(Class<?> clazz, String name, Class<F> type) {
        try {
            Field field = clazz.getDeclaredField(name);
            field.setAccessible(true);
            return type.cast(field.get(null));
        } catch (Exception e) {
            FailException.fail("Failed to get static private field " + name + " from " + clazz.getName() + ": " + e.getMessage());
            return null;
        }
    }

    /** Set the value of a private static field */
    static void set(Class<?> clazz, String name, Object value) throws Exception {
        Field field = clazz.getDeclaredField(name);
        field.setAccessible(true);
        field.set(null, value);
    }

    /** Invoke a private static method */
    static <R> R call(Class<?> clazz, String name, Class<R> returnType, Class[] paramTypes, Object[] args) throws Exception {
        Method method = clazz.getDeclaredMethod(name, paramTypes);
        method.setAccessible(true);
        return returnType.cast(method.invoke(null, args));
    }
}

Test Class Definition

/**
 * Simple class with a private instance field and a private static field.
 */
public class PriBase {
    private String name = "FunTester";
    private static String cname = "CFunTester";
}

Testing Instance Field Access

import com.funtester.frame.SourceCode;
import com.funtester.utils.PriUtil;

class PriTest extends SourceCode {
    public static void main(String[] args) {
        // Create first instance and modify its private field
        PriBase base = new PriBase();
        PriUtil.set(base, "name", "ModifiedName");
        String value1 = PriUtil.get(base, "name", String.class);
        output(value1); // prints ModifiedName

        // Create a second instance to prove the change is instance‑specific
        PriBase base2 = new PriBase();
        String value2 = PriUtil.get(base2, "name", String.class);
        output(value2); // prints FunTester
    }
}

The console shows ModifiedName for the first object and the original FunTester for the second, confirming that the utility correctly manipulates private instance fields without affecting other instances.

Testing Static Field Access

import com.funtester.frame.SourceCode;
import com.funtester.utils.PriUtil;

class PriTest extends SourceCode {
    public static void main(String[] args) {
        // Modify the private static field
        PriUtil.set(PriBase.class, "cname", "ModifiedStaticName");
        String staticValue = PriUtil.get(PriBase.class, "cname", String.class);
        output(staticValue); // prints ModifiedStaticName
    }
}

The output displays the updated static value, demonstrating that PriUtil works for class‑level members as well.

Conclusion

By calling setAccessible(true) through the PriUtil helper, developers can read, modify, and invoke private instance or static members at runtime without altering the original source code. This approach eliminates the boiler‑plate of manual reflection and provides a reusable, type‑safe API for accessing otherwise inaccessible fields and methods.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendJavaReflectionutilityPrivateFields
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.