Java Beautifier & Formatter

Java arrives broken in a handful of familiar ways. A bug report carries sixty lines of source pasted at column zero. A patch mixes tabs into a file built on spaces. Somebody drops a whole class into a chat message as one long line. Paste it on the left and the layout is rebuilt from the braces, annotations, and generics found in your own source.

Braces
Indent
Imports
Your JavaEdit freely, nothing here is changed
FormattedRead only
Paste Java on the left, or load the sample.

Your original stays in the left pane

Most beautifiers rewrite in place and leave you hunting through undo history to see what moved. Here the source and the result sit side by side, so you read both before deciding the rewrite is an improvement. Press CtrlEnter to reformat without reaching for the mouse. Send Back moves the formatted text into the left pane when you want a second pass at a different indent width.

Switching any setting reformats straight away, so you compare 2 spaces against 4, or attached braces against Allman, by clicking twice.

What gets rebuilt

Every line is regenerated rather than patched. Your source runs through a Java tokenizer first, so string literals, character constants, text blocks, comments, and annotations are set aside before a single spacing rule fires. A brace inside a string no longer throws the indentation off by a level.

  • Indentation comes from brace depth at the width you pick. Existing tabs and mixed leading whitespace are discarded outright.
  • Statements break at semicolons outside a for header, so one statement gets one line.
  • Annotations on a type, field, or method move onto their own line above the declaration. Parameter annotations stay inline, where @Nullable String label belongs.
  • Generic arguments stay tight. Map<String, List<Integer>> keeps its stacked closing brackets, the diamond in new ArrayList<>() survives, and a shift like x >> 2 is still read as arithmetic.
  • Lambda arrows and method references get the spacing Java readers expect: s -> s.trim() and String::trim.
  • Both switch forms work. Colon labels indent under switch with the body on the next line, arrow labels stay on one line.
  • Casts keep their gap, so (String) obj rather than (String)obj, and a negative literal after a cast stays glued to its minus sign.
  • Empty bodies collapse to {}, trailing whitespace goes, and runs of blank lines collapse to one.
  • A blank line lands after every method, type, and enum body.

The status bar under the panes reports what came out: line counts either side, how many type bodies and methods were found, and how deep the nesting goes. Nesting past four levels in a single method is worth a second look before the formatting question matters at all.

The import block is the part worth automating

Imports rot faster than anything else in a Java file. A merge drops a duplicate in, a refactor leaves a stale entry behind, and nobody notices because the compiler stays quiet about order. Set Imports to Tidy and the block is deduplicated, sorted inside each group, and separated by blank lines.

GroupMatchesExample line
FirstThe standard libraryimport java.time.Instant;
SecondJava EE and Jakarta EEimport javax.annotation.Nullable;
ThirdThird party code and your own packagesimport com.toolexe.reports.Reading;
LastStatic importsimport static java.util.Comparator.comparing;

This order is a choice, not a standard. IntelliJ ships with the first three groups reversed, and google-java-format puts static imports first in a single block with no separators at all. None of the three is wrong, and the one your repository already uses is the one to keep. Leave is a click away for exactly that reason.

Tidy touches a run of imports only when nothing but blank lines sits between them. A comment parked between two imports stops the rewrite, because moving lines around a comment changes what the comment points at. Unused imports survive too, since this page never sees the rest of your classpath and a guess there would delete working code.

Attached braces, or Allman for the code you inherited

Java settled this argument early. The Oracle code conventions, the Google Java Style guide, and the default in every mainstream IDE all put the opening brace at the end of the line it belongs to. Attached is the default here and the right answer for new code.

Allman earns its place on files that arrived from somewhere else. Ported C# rarely gets rewritten, generated adapters follow whatever the generator felt like, and a lot of 2005 era enterprise Java came out of a template with the brace on its own line. Reading those is easier at the shape they were written in, and reformatting the whole file to prove a point buries the real diff and makes git blame useless for that region.

Picking an indent width

WidthWhere it comes from
4 spacesOracle code conventions, and the out of the box setting in IntelliJ IDEA and Eclipse
2 spacesGoogle Java Style, common in Android work and Kotlin adjacent projects
8 spacesOlder Sun sample code and a few long lived Apache projects
TabFiles governed by an .editorconfig with indent_style set to tab

Continuation lines are a separate rule in both style guides, 8 spaces for Oracle and 4 for Google. This page never wraps a line, so continuation indent never comes up. That gap is the biggest difference between what you read here and what google-java-format writes to disk.

What it leaves exactly as you wrote it

  • Text blocks. Everything between the triple quotes survives character for character, closing delimiter included. The position of those closing quotes decides how much incidental whitespace the compiler strips, so moving them would change your string.
  • Javadoc and comment wording. Comment lines are re-indented to match their block. The text inside is never touched, rewrapped, or reordered.
  • String and character literals, escape sequences included.
  • Line breaks inside array and collection initializers. A lookup table you spread over six lines stays over six lines.
  • Method chains. A stream pipeline written on one line stays on one line, whatever its width.
  • Blank lines between members, collapsed to one each.

Where this stops short

  • No line length limit and no wrapping. A 200 character stream chain comes out 200 characters wide.
  • No continuation indent rules, so nothing gets aligned under an opening parenthesis.
  • Unused imports stay put. Only a compiler with your full classpath knows what is reachable.
  • Generic detection is a lookahead heuristic. An unusual comparison written as a < b, c > d inside an argument list will confuse it.
  • Annotation members are never split across lines, so a long @RequestMapping stays on one line.
  • Files past roughly 2 MB are refused rather than freezing the tab.
  • Kotlin, Groovy, and Scala are near enough to look right and far enough to come out wrong. Reach for a formatter built for them.

The output will not match google-java-format line for line, and matching it is not the goal. This page exists for reading code somebody pasted at you. What lands in a commit should go through the config your repository already carries.

Moving the job into the build

Three commands cover almost every Java codebase, and all of them run offline in a pre-commit hook or a CI step.

google-java-format -i src/main/java/com/toolexe/reports/SampleWindow.java ./gradlew spotlessApply mvn com.spotify.fmt:fmt-maven-plugin:format

Commit the settings so layout stops being a personal preference:

// build.gradle plugins { id 'com.diffplug.spotless' version '6.25.0' } spotless {java {googleJavaFormat('1.22.0')removeUnusedImports()importOrder('java', 'javax', '', '\\#')trimTrailingWhitespace()endWithNewline()}}

Spotless gives you spotlessCheck in CI, so a badly formatted patch fails the build instead of starting an argument in review. The '\\#' entry in that import order is the static group, and moving it to the front matches google-java-format. Pair the build config with an .editorconfig so editors agree long before the build runs:

# .editorconfig [*.java]indent_style = space indent_size = 4 max_line_length = 100 trim_trailing_whitespace = true insert_final_newline = true

Checkstyle covers the rules a formatter cannot reach, naming, import restrictions, method length. Run it alongside Spotless rather than instead of it, because the two answer different questions.

Java formatting questions

Does my Java source get uploaded anywhere?

No. The tokenizer and the printer are JavaScript running inside this page, so nothing is posted to a server. That matters when the code belongs to an employer or sits under a client NDA.

The indentation goes wrong halfway down my file. Why?

Almost always an unbalanced brace. Check the status bar under the two panes. When it reports a missing brace, fix that first, because every indent decision after the bad brace is built on the wrong depth.

Does it remove unused imports?

No. It deduplicates and sorts, nothing further. Removing an unused import safely needs the whole classpath, and this page only sees the text you pasted. Use Spotless with removeUnusedImports() or your IDE for that job.

Which indent width should a new Java project use?

4 spaces, unless you have a reason to follow Google Java Style, which uses 2. Consistency across the repository matters more than the number itself. Commit an .editorconfig so the choice stops being a per developer setting.

Will it reformat my text blocks?

No. Everything between the triple quotes is preserved, closing delimiter included. The indentation of that closing delimiter controls how much whitespace Java strips at compile time, so touching it would change the value of your string.

Does the output match google-java-format?

Close on braces, spacing, and indentation. Not on line wrapping, which this page never does. For anything heading into a commit, run google-java-format or Spotless locally and let this page stay a reading tool.