java - Make String.format("% s", arg) muestra los argumentos de valor nulo de manera diferente a "null"
string-formatting (10)
Considere la implementación toString()
de un bean:
@Override
public String toString() {
String.format("this is %s", this.someField);
}
Esto da como resultado que this is null
si someField
es nulo.
¿Hay alguna forma de anular la representación de cadena null
predeterminada de los argumentos de valor nulo en otro texto, es decir ?
sin llamar explícitamente replaceAll(...)
en el método toString
?
Nota : el bean se hereda de una superclase que podría implementar Formattable
( http://docs.oracle.com/javase/7/docs/api/java/util/Formattable.html ) pero parece que no entiendo cómo hacer que esto funcione
EDITAR : El fragmento de código está simplificado en exceso por ejemplo, pero no estoy buscando soluciones de operador ternario someField==null ? "?" : someField
someField==null ? "?" : someField
someField==null ? "?" : someField
porque:
- puede haber (potencialmente) muchos campos involucrados en
toString()
por lo que verificar todos los campos es demasiado engorroso y no es fluido. - otras personas sobre las que tengo poco control (si las hay) están escribiendo sus propias subclases.
- si se llama a un método y se devuelve un valor nulo, esto implicaría llamar al método dos veces o declarar una variable local.
Más bien, ¿se puede hacer algo utilizando la interfaz Formattable
o teniendo un Formatter
personalizado (que es el final
cierto)?
Con java 8 ahora puedes usar la clase opcional para esto:
import static java.util.Optional.ofNullable;
...
String myString = null;
System.out.printf("myString: %s",
ofNullable(myString).orElse("Not found")
);
Desde Java 7, puede usar Objects.toString(Object o, String nullDefault)
.
Aplicado a su ejemplo: String.format("this is %s", Objects.toString(this.someField, "?"));
La mejor solución, en mi opinión, es usar el método de Objetos de Guava, firstNonNull. El siguiente método asegurará que imprimirá una cadena vacía si alguna parte del campo es nula.
String.format("this is %s", MoreObjects.firstNonNull(this.someField, ""));
Para evitar repetir el operador ternario, puede envolverlo en un método más legible que verificará si su objeto es null
y devolverá algún valor predeterminado si es verdadero como
static <T> T changeNull(T arg, T defaultValue) {
return arg == null ? defaultValue : arg;
}
uso
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, ""));
salida:
field is
id is -1
id is
Para mantener el valor original de someField
(en caso de que null sea un valor válido), puede utilizar un operador ternario .
String.format("This is %s", (this.someField == null ? "unknown" : this.someField));
Para una solución Java 7 que no requiere bibliotecas externas:
String.format("this is %s", Objects.toString(this.someField, "?"));
Si no desea utilizar replaceAll()
, puede asignar un texto predeterminado (Cadena) para someField
.
Pero si algún tiempo esto puede asignar null
nuevo. Así que puedes usar la validación para ese caso.
this.someField == null ? "defaultText" : this.someField
Un poco tarde en el tema, pero esto podría ser una solución bastante limpia: primero, cree su propio método de formato ...
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);
}
Entonces, úsalo como lo harás ...
@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);
}
Esto elimina la necesidad de múltiples operadores ternarios difíciles de leer.
Usted podría simplemente hacer
String.format("this is %s", (this.someField==null?"DEFAULT":this.someField));
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);
}
entonces usa el método, ok