Reflection
Private Field
Programming
Java
C#

Find a private field with Reflection?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Reflection lets you inspect types at runtime and, if necessary, reach members that normal code cannot access directly. That includes private fields, although doing so should be a deliberate last resort rather than a routine design pattern.

Why Private Fields Are Hard to Reach

Private fields exist to preserve encapsulation. A class can change how it stores internal state without breaking callers, because callers are not supposed to depend on those details. Reflection bypasses that rule.

That is why reflective access is powerful but risky:

  • it couples your code to implementation details
  • it can break after refactors
  • it may be restricted by runtime security rules
  • it is slower and harder to read than normal member access

Still, there are valid uses in tests, debugging tools, serializers, framework code, and migration utilities.

Finding a Private Field in Java

In Java, use getDeclaredField() when you already know the field name. Unlike getField(), it can find non-public members declared on the class itself.

java
1import java.lang.reflect.Field;
2
3class User {
4    private String token = "secret-value";
5}
6
7public class ReflectionDemo {
8    public static void main(String[] args) throws Exception {
9        User user = new User();
10
11        Field field = User.class.getDeclaredField("token");
12        field.setAccessible(true);
13
14        String value = (String) field.get(user);
15        System.out.println(value);
16    }
17}

Key points:

  • 'getDeclaredField("token") searches the declared members of User'
  • 'setAccessible(true) bypasses normal Java access checks'
  • 'field.get(user) reads the value from a specific instance'

If the field is declared in a superclass, you need to walk the class hierarchy manually.

Searching Superclasses in Java

Here is a reusable helper that finds a private field by name, even if it lives higher up the inheritance chain:

java
1import java.lang.reflect.Field;
2
3public class FieldFinder {
4    public static Field findField(Class<?> type, String name) throws NoSuchFieldException {
5        Class<?> current = type;
6
7        while (current != null) {
8            try {
9                Field field = current.getDeclaredField(name);
10                field.setAccessible(true);
11                return field;
12            } catch (NoSuchFieldException ignored) {
13                current = current.getSuperclass();
14            }
15        }
16
17        throw new NoSuchFieldException(name);
18    }
19}

This is useful when working with framework base classes or inherited models.

Finding a Private Field in C#

In C#, use reflection with BindingFlags:

csharp
1using System;
2using System.Reflection;
3
4public class User
5{
6    private string token = "secret-value";
7}
8
9public class Program
10{
11    public static void Main()
12    {
13        var user = new User();
14        var field = typeof(User).GetField(
15            "token",
16            BindingFlags.Instance | BindingFlags.NonPublic
17        );
18
19        string value = (string)field.GetValue(user);
20        Console.WriteLine(value);
21    }
22}

Here, BindingFlags.NonPublic allows private members to be found, and BindingFlags.Instance tells reflection to search instance fields rather than static ones.

To search inherited fields, you may need to inspect BaseType repeatedly, just as you would in Java.

Reading and Writing Private Values

Once you have the reflected field, you can both read and modify it.

Java write example:

java
Field field = User.class.getDeclaredField("token");
field.setAccessible(true);
field.set(user, "new-token");

C# write example:

csharp
field.SetValue(user, "new-token");

This ability is exactly why reflection should be used carefully. Changing internal state can violate invariants that the class normally protects through constructors or setter methods.

When Reflection Is Justified

Good reasons to reflect over private fields include:

  • testing legacy code that cannot easily be refactored
  • framework or library infrastructure
  • object mapping, serialization, or migration tools
  • debugging and diagnostic tooling

Bad reasons include:

  • avoiding a small API design improvement
  • working around encapsulation in normal business logic
  • depending on internal details of third-party libraries for production paths

If you control the class, adding a proper method or constructor is usually better than reflective access.

Common Pitfalls

  • Using getField() in Java only searches public fields and often returns nothing useful for this task.
  • Forgetting BindingFlags.NonPublic in C# leads to null and confusion.
  • Assuming the field is on the concrete class when it is actually inherited from a base type causes lookup failures.
  • Mutating private fields can break object invariants and produce bugs that are difficult to trace.
  • Reflection-heavy code is brittle under renames and refactors because field names are string-based.

Summary

  • Reflection can find private fields, but it intentionally bypasses encapsulation.
  • In Java, use getDeclaredField() and usually setAccessible(true).
  • In C#, use GetField() with BindingFlags.Instance | BindingFlags.NonPublic.
  • If the field may be inherited, walk the class hierarchy.
  • Prefer public APIs or refactoring when you control the codebase, and use reflection only when the tradeoff is justified.

Course illustration
Course illustration

All Rights Reserved.