51

Consider the custom toString() implementation of a bean:

@Override
public String toString() {
    String.format("this is %s", this.someField);
}

This yields this is null if someField is null.

Is there a way to override the default null string representation of null-valued arguments to another text, i.e., ? without calling explicitly replaceAll(...) in the toString method?

Note: The bean inherits from a superclass that could implement Formattable (http://docs.oracle.com/javase/7/docs/api/java/util/Formattable.html) but I just don't seem to understand how to make this work.

EDIT: The snippet is over-simplified for the sake of example but I'm not looking for ternary operator solutions someField==null ? "?" : someField because:

  • there can be (potentially) a great many fields involved in toString() so checking all fields is too cumbersome and not fluent.
  • other people whom I have little control over (if any) are writing their own subclasses.
  • if a method is called and returns null that would either imply calling the method twice or declaring a local variable.

Rather, can anything be done using the Formattable interface or having some custom Formatter (which is final btw.)?

5
  • 2
    I would do String.format("this is %s", this.someField==null?"?":this.someField); Commented Dec 5, 2013 at 16:02
  • 1
    Or with Guava : String.format("this is %s", Objects.firstNotNull(this.someField, "?")); Commented Dec 5, 2013 at 16:03
  • I always think fondly of firstNotNull, esp. similar implementations some SQL dialects, but Guava is too heavy a dependence and belongs more to the dependencies a Utils class than that of a pojo, imo.
    – VH-NZZ
    Commented Dec 5, 2013 at 16:42
  • @VH-NZZ There are some great solutions. Sure you can't choose one to accept?
    – Kim Kern
    Commented Jan 30, 2019 at 10:13
  • @KimKern Most, if not all, somehow address the issue and ultimately produce a result compatible with the question, albeit at some expense. That being said, I objectively can't assert that I can pick one answer as truly superior, hence: no, at this stage I'm afraid I can't.
    – VH-NZZ
    Commented Jan 31, 2019 at 7:01

10 Answers 10

63

With java 8 you can now use Optional class for this:

import static java.util.Optional.ofNullable;
...
String myString = null;
System.out.printf("myString: %s",
    ofNullable(myString).orElse("Not found")
);
1
  • To apply for also 'empty' values, it can be extended with 'filter(s -> !s.isEmpty())' as the following: System.out.printf("myString: %s", ofNullable(myString).filter(s -> !s.isEmpty()).orElse("Not found")
    – burak
    Commented Oct 1, 2020 at 15:41
48

For a Java 7 solution that doesn't require external libraries:

String.format("this is %s", Objects.toString(this.someField, "?"));
1
  • With Java 17 you could use: "this is %s".formatted("this is %s", Objects.toString(this.someField, "?")) Commented Jul 20, 2023 at 11:51
22

The nicest solution, in my opinion, is using Guava's Objects method, firstNonNull. The following method will ensure you will print an empty string if someField is ever null.

String.format("this is %s", MoreObjects.firstNonNull(this.someField, ""));

Guava docs.

1
  • 10
    String.format("this is %s", StringUtils.defaultIfBlank(this.someField, "")); will do the trick if Apache StringUtils happens to be on your classpath.
    – dvtoever
    Commented Dec 18, 2015 at 12:25
6

A bit late on the subject, but this could be a quite clean-looking solution : First, create your own format method...

private static String NULL_STRING = "?";

private static String formatNull(String str, Object... args){
    for(int i = 0; i < args.length; i++){
        if(args[i] == null){
            args[i] = NULL_STRING;
        }
    }

    return String.format(str, args);
}

Then, use it as will...

@Test
public void TestNullFormat(){
    Object ob1 = null;
    Object ob2 = "a test";

    String str = formatNull("this is %s", ob1);
    assertEquals("this is ?", str);

    str = formatNull("this is %s", ob2);
    assertEquals("this is a test", str);
}

This eliminates the need for multiple, hard-to-read, ternary operators.

2
  • 1
    ... but implies a dependency on your formatNull method.
    – VH-NZZ
    Commented Apr 10, 2014 at 14:39
  • Of course! Unless the case forementionned is specific to some output strategy class, where the method can be defined privately in the strategy itself. Then there would be no depenedency problem. If it is used at many places in the application, then yes it would need to be put in some library / util class.
    – JM Lord
    Commented Apr 12, 2014 at 1:49
5

If you don't want to use replaceAll(), You can assign a default text(String) for someField.

But if some time this may assign null again. So you can use validation for that case

 this.someField == null ? "defaultText" : this.someField
0
4

To avoid repeating ternary operator you can wrap it in more readable method that will check if your object is null and return some default value if it is true like

static <T> T changeNull(T arg, T defaultValue) {
    return arg == null ? defaultValue : arg;
}

usage

String field = null;
Integer id = null;
System.out.printf("field is %s %n", changeNull(field, ""));
System.out.printf("id is %d %n", changeNull(id, -1));
System.out.printf("id is %s %n", changeNull(field, ""));

output:

field is  
id is -1 
id is  
3

You could just do

String.format("this is %s", (this.someField==null?"DEFAULT":this.someField));
1
  • Again, this is using the ternary operator. Thanks anyway.
    – VH-NZZ
    Commented Jan 11, 2014 at 13:24
3
public static String format(String format, Object... args){
    for (int i=0;i<args.length;i++){
        if (args[i]==null) args[i]="";
    }
    return String.format(format,args);
}

then use the method ,ok

3

From java 7, you can use Objects.toString(Object o, String nullDefault).

Applied to your example: String.format("this is %s", Objects.toString(this.someField, "?"));

1

To keep the original value of someField (in case null is a valid value), you can use a ternary operator.

String.format("This is %s", (this.someField == null ? "unknown" : this.someField));

Not the answer you're looking for? Browse other questions tagged or ask your own question.