Сделать String.format("% s", arg) отображать аргументы с нулевым значением, отличные от "null"

Рассмотрим пользовательскую реализацию toString() компонента:

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

Это дает значение this is null если someField имеет значение NULL.

Есть ли способ переопределить стандартное представление null строки нулевых аргументов другому тексту, т.е. ? без вызова явно replaceAll(...) в методе toString?

Примечание. Боб наследуется от суперкласса, который может реализовать Formattable (http://docs.oracle.com/javase/7/docs/api/java/util/Formattable.html), но я просто не понимаю, как сделайте эту работу.

EDIT: фрагмент упрощен для примера, но я не ищу тройные операторские решения someField==null? "?": someField someField==null? "?": someField someField==null? "?": someField потому что:

  • может быть (потенциально) большое количество полей, вовлеченных в toString() поэтому проверка всех полей слишком громоздка и не является беглостью.
  • другие люди, которым я мало контролирую (если они есть), пишут собственные подклассы.
  • если метод вызывается и возвращает значение null, которое подразумевало бы вызов метода дважды или объявление локальной переменной.

Скорее всего, что-то можно сделать с использованием интерфейса Formattable или с помощью какого-то пользовательского Formatter (который является final btw.)?

Ответы

Ответ 1

С помощью java 8 теперь вы можете использовать дополнительный класс:

import static java.util.Optional.ofNullable;
...
String myString = null;
System.out.printf("myString: %s",
    ofNullable(myString).orElse("Not found")
);

Ответ 2

Самое приятное решение, на мой взгляд, использует метод Guava Objects, firstNonNull. Следующий метод гарантирует, что вы напечатаете пустую строку, если someField всегда имеет значение null.

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

Гуава.

Ответ 3

Для решения Java 7, которое не требует внешних библиотек:

String.format("this is %s", Objects.toString(this.someField, "?"));

Ответ 4

Если вы не хотите использовать replaceAll(), вы можете назначить текст по умолчанию (String) для someField.

Но если некоторое время это может снова присвоить значение null. Таким образом, вы можете использовать валидацию для этого случая

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

Ответ 5

Немного поздно по этому вопросу, но это может быть довольно чистое решение: во-первых, создайте свой собственный формат...

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);
}

Затем используйте его как будет...

@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);
}

Это устраняет необходимость в нескольких, трудночитаемых, тройных операторах.

Ответ 6

Чтобы избежать повторения тернарного оператора, вы можете обернуть его более читаемым методом, который будет проверять, является ли ваш объект null и возвращает значение по умолчанию, если оно истинно, как

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

Применение

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, ""));

вывод:

field is  
id is -1 
id is  

Ответ 7

Вы могли бы просто сделать

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

Ответ 8

Чтобы сохранить исходное значение someField (в случае, если null является допустимым значением), вы можете использовать тернарный оператор.

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

Ответ 9

Из java 7 вы можете использовать Objects.toString(Object o, String nullDefault).

Применяется к вашему примеру: String.format("this is %s", Objects.toString(this.someField, "?"));

Ответ 10

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);
}

затем используйте метод, ok