Raw Control Character In Literal

ID

java.escape_control_char_in_literal

Severity

high

Remediation Complexity

medium

Remediation Risk

low

Remediation Effort

medium

Resource

Code Smell

Language

Java

Tags

code_smell, readability, string

Description

Reports a String or char literal that holds a raw control character or an invisible character — an ASCII control, a Unicode whitespace character other than the plain space, or a zero-width character such as the zero-width space or the byte order mark — where an escape sequence for that character should have been written instead.

Rationale

These characters get into source by accident: a tab picked up from a terminal, a non-breaking space pasted from a document, a zero-width space carried over from an editor’s input method. Nothing marks them on screen, so the literal no longer matches what the reader sees. A comparison against the visually identical string fails, a map lookup never hits, and the review that should have caught it saw only whitespace.

They are also fragile: a reformat or a round trip through a tool that trims trailing whitespace can silently change or delete the character, so the same source behaves differently before and after an unrelated edit. Written as an escape sequence, the same character is explicit, greppable, and survives every editor.

Raw characters are told apart from their escaped spelling by reading the literal’s own text: an escaped tab and a raw tab decode to the same string, so only the way it was written can tell them apart. Because every Java escape sequence is made of printable ASCII, anything invisible found in the literal as written was typed raw.

Text blocks are not covered: their leading indentation and embedded newlines are part of how they are meant to be written, so a raw tab or space there is not necessarily a mistake. The C1 range (U+0080-U+009F) is not reported either, because legacy single-byte encodings put printable characters at those code points, so a literal that came through such an encoding would be flagged for a character its author can see. U+007F is still reported.

In the example below, the placeholders <TAB> and <ZWSP> stand for the character itself, typed straight into the literal — which is exactly what makes the defect invisible in a real file.

String header = "id<TAB>name";     // Bad -- a raw tab
String code = "AB<ZWSP>12";        // Bad -- a raw zero-width space

String escaped = "id\tname";       // Good -- escaped, and visible as such
String plain = "id name";          // Good -- a plain space

Remediation

Replace the character with its escape sequence. A tab is \t; the other named controls are \b, \f, \n and \r. Everything else takes a code point escape, written as a backslash, u and four hex digits — \u00A0 for a non-breaking space, \u200B for a zero-width space. If the character got in by accident, delete it or replace it with a plain space. When several places need the same separator, lift it to a named constant so there is a single spot to inspect.

© 2026 Xygeni. All rights reserved