Objects.toString()
Turn any value, including null, into a string without a NullPointerException, and choose what null should print as.
public static String toString(Object o)
public static String toString(Object o, String nullDefault)- Added in Java Java 7
Parameters
| Parameter | Type | Description |
|---|---|---|
$o | Object | The value to convert. May be null. |
$nullDefaultoptional | String | What to return when o is null. May itself be null. |
Return value
Stringo.toString() when o is not null. When o is null, the one-argument form returns the string "null" and the two-argument form returns nullDefault.
Errors
Nothing itself. Any exception thrown by o.toString() propagates.
Objects.toString(o) calls o.toString(), or returns the four-character string "null" if o is null. Objects.toString(o, "-") lets you choose the text for null instead. Both avoid the NullPointerException you get from calling o.toString() directly.
The two forms
The one-argument form behaves like String.valueOf(o) and like string concatenation, which also prints null. That is fine for debugging, but the word null is rarely what a user, a CSV file or a search index should see. The two-argument form is the one to reach for in output code:
String line = String.join(",",
Objects.toString(order.id(), ""),
Objects.toString(order.couponCode(), ""));Mistakes people make
- Letting
"null"leak into stored data. Convert a nullable field with the one-argument form, save it, and the column now contains the textnull, which is not SQLNULLand will not be found byIS NULL. Keep null as null, or pick an explicit default. - Using it to build JSON by hand.
"\"" + Objects.toString(x) + "\""produces the string"null", not JSONnull, and no escaping happens. Use a JSON library or a careful encoder. - Passing arrays. Arrays do not override
toString, so you get the type and an identity hash. UseArrays.toString. - Expecting
nullDefaultto apply to empty strings. Only null is replaced.
Back-end angle
Log lines, audit messages, CSV exports and response headers are built from fields that can be missing. Objects.toString(value, "-") keeps a log line readable and column-aligned, and Objects.toString(value, "") gives an empty CSV cell. For logs, prefer the logging framework's own placeholders, which handle null themselves and skip formatting when the level is off. When you want a default of the same type rather than a string, use Objects.requireNonNullElse.
Example
When to use it
- Writing CSV exports where a missing optional field should become an empty cell rather than the text null.
- Building access or audit log lines where an absent user id or request id prints as a dash.
- Rendering optional values into plain-text emails or admin screens with a friendly placeholder such as n/a.
Frequently asked questions
What is the difference between Objects.toString and String.valueOf?
For an Object argument they return the same thing, including "null" for null. Objects.toString also has a two-argument form that returns your own default for null.
How do I convert null to an empty string in Java?
Use Objects.toString(value, ""). It returns value.toString() when value is not null and "" when it is.
More examples
Null-safe ways to stringify, compared
The one-argument form, String.valueOf and concatenation all produce the text null. Only the two-argument form lets you choose something else, and calling toString directly throws.
void main() {
Object missing = null;
IO.println(Objects.toString(missing));
IO.println(String.valueOf(missing));
IO.println("value=" + missing);
IO.println(Objects.toString(missing, "-"));
try {
missing.toString();
} catch (NullPointerException e) {
IO.println("missing.toString() -> NullPointerException");
}
}
// Output:
// null
// null
// value=null
// -
// missing.toString() -> NullPointerExceptionReadable access log lines
Anonymous requests have no user id, and a dash keeps the line consistent and easy to grep. Printing the word null would look like a bug.
record Request(String method, String path, String userId, String requestId) {}
String accessLog(Request r, int status) {
return "%s %s %d user=%s req=%s".formatted(
r.method(), r.path(), status,
Objects.toString(r.userId(), "-"),
Objects.toString(r.requestId(), "-"));
}
void main() {
IO.println(accessLog(new Request("GET", "/orders/7", "u-12", "r-9f2"), 200));
IO.println(accessLog(new Request("POST", "/login", null, null), 401));
}
// Output:
// GET /orders/7 200 user=u-12 req=r-9f2
// POST /login 401 user=- req=-Only null is replaced, and arrays need Arrays.toString
An empty string is not null, so it comes back unchanged. An array prints as its type code and identity hash, so use Arrays.toString to see the contents.
void main() {
IO.println("[" + Objects.toString("", "n/a") + "]");
IO.println("[" + Objects.toString(null, "n/a") + "]");
int[] scores = {3, 5, 8};
IO.println(Objects.toString(scores).startsWith("[I@"));
IO.println(Arrays.toString(scores));
}
// Output:
// []
// [n/a]
// true
// [3, 5, 8]
Discussion