What does setAccessible(true) do, and why might you call it when using reflection?
answer
- AccessibleObject.setAccessible(true) suppresses access checks
- Per reflection-object flag, not per class
- Used by Jackson/Hibernate/Spring/tests
- Java 9+: can throw InaccessibleObjectException
- Doesn't change modifiers, only the check
basics
~10 ssetAccessible(true) tells Java to skip the normal access checks (public/private/protected) for a field, method, or constructor, so reflection can read or call a member it otherwise could not, such as a private field.
solid answer
~40 sReflection objects (Field, Method, Constructor) extend AccessibleObject. By default, using them enforces the same access rules as ordinary code: you cannot read a private field of another class. Calling setAccessible(true) suppresses those Java-language access checks for that single reflection object, letting you get/set a private field or invoke a private method. It is widely used by frameworks (Jackson, Hibernate, Spring) to populate private fields and by tests to reach internals. It returns void and throws InaccessibleObjectException (since Java 9) if the module system forbids the access. Always reset or limit its use: it bypasses encapsulation, can break when internals change, and on the module path requires the target package to be open. Prefer canAccess/trySetAccessible to probe safely rather than assuming it will succeed.
code
java · 8 linesclass Vault { private String secret = "hunter2"; }
Vault v = new Vault();
Field f = Vault.class.getDeclaredField("secret");
// f.get(v); // would throw IllegalAccessException
f.setAccessible(true); // suppress the access check for this Field
String value = (String) f.get(v); // "hunter2"
f.set(v, "changed"); // private final-less field can be writtengo deeper
Knows setAccessible(true) lets reflection touch private members and that frameworks/tests use it.
Explains it is a per-object flag on AccessibleObject, suppresses the language check (not modifiers), and is needed by serialization/DI.
Adds the Java 9 module caveat (InaccessibleObjectException), recommends trySetAccessible/canAccess, and warns about coupling to internals and final-field limits.
Frames it as a deliberate encapsulation-bypass with a security/maintainability cost; weighs designed APIs vs deep reflection and the migration implications of JPMS strong encapsulation for libraries.
**Reflection** is Java's ability, at runtime, to inspect and manipulate classes, fields, methods, and constructors that you may not have known about at compile time. You obtain these via objects of type `java.lang.reflect.Field`, `Method`, and `Constructor` (e.g. `MyClass.class.getDeclaredField("secret")`). **Access control** in normal Java is the `public`/`protected`/package-private/`private` keyword system. Code can only touch members it is permitted to: you cannot write `other.privateField` from an unrelated class. Reflection enforces these *same* rules by default — so `field.get(obj)` on a private field throws `IllegalAccessException`. `Field`, `Method`, and `Constructor` all extend the class **`AccessibleObject`**, which has the method **`setAccessible(boolean flag)`**. Calling `setAccessible(true)` sets a per-object flag that *suppresses the Java-language access checks* for that one reflection object. After it returns successfully, `field.get(obj)` / `field.set(obj, v)` / `method.invoke(obj, ...)` work even on `private` members. Calling `setAccessible(false)` restores checking. **Why anyone does this:** frameworks need to do things ordinary code can't. Serialization libraries (Jackson, Gson) read/write private fields; ORM/DI frameworks (Hibernate, Spring) inject into private fields and call private constructors; test code reaches internals to assert on them. Dependency injection and deserialization fundamentally require reaching non-public members of *other* classes. **Important nuances:** - It operates on a *single* reflection object, not the whole class. You must call it on each `Field`/`Method` you obtained. - It does **not** change the member itself or its modifiers — it only turns off the *check* when you use that handle. (You cannot, for example, remove `final` this way reliably.) - Since **Java 9 (the module system / JPMS)** it can fail with **`InaccessibleObjectException`** (an unchecked `RuntimeException`) when the target type is in a module that has not *opened* its package for deep reflection. This is the headline change covered in the related questions. - It is a *checked-style* security-sensitive operation: under a `SecurityManager` (deprecated for removal) it could throw `SecurityException`. **Caveats / good practice:** bypassing access defeats encapsulation, so the code becomes coupled to private internals that can change between library versions. Prefer designed APIs when they exist; use `trySetAccessible()` (returns `boolean`, never throws) or `canAccess(obj)` to probe instead of assuming success; and on the module path, ensure the package is `open` rather than relying on it working by luck on the classpath.
- Does setAccessible(true) on one Field affect other reflection objects for the same class?No. The flag lives on the individual AccessibleObject (that specific Field/Method/Constructor). You must call it on each handle you want to use; obtaining a fresh Field gives you a fresh, checked one.
- What is the difference between IllegalAccessException and InaccessibleObjectException here?IllegalAccessException is thrown at use time (get/invoke) when you never suppressed the language access check. InaccessibleObjectException is thrown by setAccessible itself (Java 9+) when the module system forbids opening the member for deep reflection — a stronger, module-level refusal you cannot override from code.
It is a backstage pass for one specific door: it lets you through that door's lock check, but it doesn't unlock the building or move the door — and a stricter venue (a module) can refuse to honor the pass.
saying these in an interview costs you the question
- Saying setAccessible(true) changes the field's visibility or removes 'private' permanently — it only suppresses the check for that handle.
- Claiming it reliably removes 'final' so you can mutate final fields — modern JVMs do not honor writes to final fields via reflection in general.
- Thinking it always succeeds on Java 9+ — it can throw InaccessibleObjectException under the module system.
- Assuming one call covers a whole class rather than a single reflection object.