The toString Method
The toString Method
Every object in Java has a built-in ability to represent itself as text. That ability comes from the toString() method, which is defined in java.lang.Object — the root of the entire Java class hierarchy. Because every class you write automatically inherits from Object, every object already has a toString() method before you write a single line.
What the Default toString Looks Like
The default implementation, inherited from Object, produces a string that combines the fully-qualified class name with the object's identity hash code in hexadecimal:
Let us see it in practice. Suppose you have a simple BankAccount class and you try to print it:
The output is meaningless for debugging. You cannot tell the owner or the balance just by looking at that hash code. This is exactly why overriding toString() is one of the first things an experienced Java developer does when creating a new class.
toString() on an object automatically whenever it needs a String representation: inside System.out.println(obj), during string concatenation ("Account: " + obj), and inside debuggers, loggers, and most IDE inspectors. You rarely call it by name; Java does it for you.
Overriding toString
Overriding means providing your own version of the method that replaces the inherited one. The signature must match exactly: it must be public, return a String, and take no parameters. The @Override annotation is not required, but it is strongly recommended — it tells the compiler you intend to override an inherited method, so it will catch typos or wrong signatures for you.
Now the output is immediately useful. Anyone reading a log or debugging in an IDE can understand the object at a glance.
Formatting Numbers in toString
Raw double values can produce ugly output like 1500.0000000001 due to floating-point precision. Use String.format() to control the presentation:
%.2f formats a floating-point number to exactly two decimal places — perfect for currency.
%s is a string slot and %d is an integer slot.
A Realistic Multi-Field Example
Here is a Product class with several fields to show how toString() scales:
toString and String Concatenation
Because Java calls toString() automatically during concatenation, you can embed objects directly in larger strings:
toString() that includes passwords, credit card numbers, or secret keys is a security risk — those strings end up in logs, stack traces, and error messages that may be visible to unintended audiences. Include only fields that are safe to display publicly.
Common toString Styles
There is no single required format, but the Java community tends to use a few consistent patterns:
- Curly-brace style —
ClassName{field1=value1, field2=value2}(used in the examples above, matches what IDEs generate by default) - Bracket style —
ClassName[field1=value1, field2=value2] - Prose style — a natural-language sentence, useful when the object is shown to end users rather than developers
Choose the style that fits your audience. Use the curly-brace or bracket style for developer-facing output; use a natural sentence when the string appears in a UI or email.
Summary
The toString() method turns any object into a human-readable string. The default inherited version from Object produces a hex hash that is useless for debugging. By overriding it with @Override public String toString() you gain meaningful output in println, string concatenation, logs, and debuggers — all for free. Keep sensitive fields out, use String.format() for clean number formatting, and be consistent with your chosen style across the codebase.