# Java Refactoring

> Refactoring mechanics for Java: characterisation tests, small reversible steps, what behaviour preservation actually covers, risk classification, and the catalogue — Extract/Inline, Split Phase, guard clauses, Remove Flag Argument, Pull Up and Push Down, Replace Conditional with Polymorphism or sealed types. What to detect is java-code-smells; evolution rules for published APIs are java-api-design. Use when restructuring code without changing behaviour, when a change is needed in code that has no tests, when a method resists extraction because everything shares locals, when inverting a condition into a guard clause, when converting an instanceof chain to a switch, when moving members through a hierarchy, or when you need to know whether a step crosses a lock, transaction, serialisation or published boundary and must stop. Getting a class that constructs its own dependencies into a harness in the first place is java-legacy-code-testing.

- Skill: `robsonkades/java-refactoring` (Agent Skill, multi-file: 10 files)
- Install (CLI): `npx skillmds@latest add robsonkades/java-refactoring`
- Raw SKILL.md: https://api.skillmd.com/api/skills/robsonkades/java-refactoring/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: robsonkades (https://skillmd.com/u/robsonkades)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/robsonkades/java-refactoring

---


# Java Refactoring

## Purpose

Behaviour preservation is a claim, and claims need evidence. This skill exists to
prevent the two ways "refactoring" goes wrong: the rewrite wearing refactoring's name —
no tests, big steps, behaviour quietly changed — and the refactoring that compiles
everywhere but breaks clients, because a step crossed a binary- or source-compatibility
line nobody checked.

## Workflow

The catalogue is authored for Java 25; inspect the target release/toolchain, preview policy,
resolved framework versions and CI/runtime before using a version-sensitive technique. Java 21
supports pattern switches but not the final Java 25 flexible-constructor-body feature; do not
upgrade or enable preview to make a refactoring example fit. Snippets elide imports, enclosing
classes and domain helpers; they are illustrations rather than standalone compilation units.

1. **Establish and record the baseline.** Run the affected tests. They should be green;
   if unrelated failures already exist, record them precisely and require the
   same baseline after each step rather than claiming an all-green suite. If the changed path
   has no meaningful coverage, write
   characterisation tests first — read `references/safety-workflow.md`, which includes
   a worked example. No net, no refactoring. The one exception is the step that makes the
   net possible at all: when the class cannot be constructed or the method cannot be
   reached, breaking that dependency is done without tests, under the constraints in
   `java-legacy-code-testing`.
2. **Classify the boundary.** Private or package scope lowers source-compatibility risk, but
   does not remove concurrency, reflection, persistence or serialization contracts. If a
   framework reaches the name at runtime (JPA field access, Jackson, JPQL, reflective config), in
   which case it is case 4 of `references/compatibility.md` whatever the modifier says.
   Public within the codebase: every caller moves in the same change. Exported from a
   module or published to external clients: read `references/compatibility.md` before
   touching any signature — some steps must stop or become deprecation cycles.
3. **Classify the risk and name the dimensions at stake.** Read
   `references/behaviour-preservation.md` and decide, before the first step, which
   observable dimensions this step can touch — exception type, side-effect order,
   transaction boundary, emitted SQL or events, iteration order, memory visibility —
   and which proof each of those dimensions demands. Selecting the dimensions is what
   makes step 5's "run tests" mean something.
4. **Choose the technique** from the catalogue, routed by what is being reshaped:
   `references/techniques.md` for the core moves and the design choices,
   `references/catalogue-statements-and-data.md` for statements, loops and locals,
   `references/catalogue-conditionals.md` for branching,
   `references/catalogue-api-shape.md` for signatures,
   `references/catalogue-inheritance.md` for hierarchies. Every entry in the four
   catalogue files carries a labelled precondition — check it before the step, not after.
5. **Take one mechanical step: transform, compile, test, inspect the diff.** Commit only when
   explicitly requested; the small-step discipline also applies to uncommitted work. Where an IDE
   refactoring is available, use it: it resolves references the compiler will not report.
   Editing by hand — which is the agent's case — the substitute is the compiler plus an
   explicit caller enumeration: make the old symbol inaccessible and compile, then search
   the old name as a string across resources, XML, JPQL and annotations. Grep alone is
   not the enumeration. Automating the step across many files is
   refactoring-automation's.
6. **Repeat until done, then re-run the detection pass** (java-code-smells) to confirm
   the finding that motivated the work is actually gone.

## Rules

- A refactoring commit contains no behaviour change. A bug discovered mid-refactoring
  is recorded and fixed in its own commit, before or after — never inside.
- Each commit is coherent, buildable and revertible in reverse order. If rollback needs an
  unrelated semantic repair or data recovery, the step crossed more than a code-refactoring boundary.
- A new failure after a step is diagnosed against the recorded baseline. Revert when the step
  caused it; do not patch production or dismiss a flaky/external failure without evidence.
- Do not weaken a contract assertion merely to get green. Implementation-coupled assertions may
  need mechanical updates while externally observable behavior stays fixed; explain why the
  assertion was not part of the contract and retain stronger outcome evidence.
- Renaming or reshaping anything exported, published, persisted or serialized crosses an
  evolution boundary. Java signatures route to java-api-design, wire schemas to
  rpc-and-api-contracts/schema-evolution-and-compatibility, and native Java serialization
  to java-serialization-hardening.
- Do not justify a refactoring by performance without a measurement. Restructuring
  changes allocation and dispatch patterns in both directions; claim readability, or
  bring a benchmark.

## References

- [Technique catalogue](references/techniques.md) — the core moves (Extract/Inline,
  Move, Rename, Parameter Object, Replace Type Code, Encapsulate Collection) and the
  design choices between them. Read when choosing or executing a step.
- [Statements, loops and data](references/catalogue-statements-and-data.md) — Slide
  Statements, Split/Combine Loops, Split Phase, Split Variable, Replace Temp with Query,
  Replace Derived Variable with Query, reference↔value. Read when a method resists
  extraction, or before reordering anything.
- [Conditional logic](references/catalogue-conditionals.md) — Decompose Conditional,
  guard clauses, Consolidate, Introduce Special Case, Introduce Assertion, instanceof
  chain to pattern switch. Read before inverting any condition or otherwise changing
  branching.
- [Reshaping a signature](references/catalogue-api-shape.md) — Change Function
  Declaration, Encapsulate Variable, Separate Query from Modifier, Remove Flag Argument,
  Preserve Whole Object, Remove Setting Method, Replace Constructor with Factory. Read
  when the change is visible to callers.
- [Moving members through a hierarchy](references/catalogue-inheritance.md) — Pull Up
  and Push Down, Extract Superclass, Collapse Hierarchy, Replace Subclass or Superclass
  with Delegate. Read before touching any `extends`, or before creating one.
- [Behaviour preservation](references/behaviour-preservation.md) — the dimensions of
  observable behaviour, risk classification, the places the compiler and the tests both
  lie, and the evidence ladder. Read at step 3 — it is what produces the classification.
- [Safety workflow](references/safety-workflow.md) — characterisation tests end to
  end, with a worked example that pins a bug on purpose. Read whenever coverage is
  missing or untrusted.
- [Compatibility](references/compatibility.md) — which changes break binary, source or
  behavioural compatibility, and where a refactoring must stop. Read before any step
  that touches a public or exported signature.

## Primary sources

- [JLS 13 — Binary Compatibility](https://docs.oracle.com/javase/specs/jls/se25/html/jls-13.html)
- [JLS 17 — Threads and Locks](https://docs.oracle.com/javase/specs/jls/se25/html/jls-17.html)
- [JEP 441 — Pattern Matching for switch](https://openjdk.org/jeps/441)
- [JEP 513 — Flexible Constructor Bodies](https://openjdk.org/jeps/513)
- [Jakarta Persistence 3.2 specification](https://jakarta.ee/specifications/persistence/3.2/jakarta-persistence-spec-3.2.html)

