2010-03-24 16 views
38

Digamos que tengo dos variables char, y más tarde quiero concatenarlas en una cadena. Esta es la forma en que lo haría:¿Concatenar con una cadena vacía para hacer una conversión de cadena realmente tan malo?

char c1, c2; 
// ... 

String s = "" + c1 + c2; 

He visto gente que dice que el "truco" "" + es "feo", etc, y que se debe utilizar String.valueOf o Character.toString lugar. Yo prefiero esta construcción porque:

  • Yo prefiero usar característica del lenguaje en lugar de llamada a la API si es posible
    • En general, no es el idioma por lo general más estable que la API?
    • ¡Si la función de idioma solo oculta la llamada API, entonces hay una razón más poderosa para preferirla!
      • Más ¡abstracto! ¡Ocultar es bueno!
  • Me gusta que el c1 y c2 son visualmente en el mismo nivel
    • String.valueOf(c1) + c2 sugiere algo que es especial acerca c1
  • Es más corto.

¿Hay realmente un buen argumento por qué String.valueOf o Character.toString es preferible a "" +?


Anécdota: en java.lang.AssertionError, la siguiente línea aparece 7 veces, cada una con un tipo diferente:

this("" + detailMessage); 
+0

Por supuesto 'String.valueOf (c1) + c2' sería extraño, si sigues esa ruta escribirías' String.valueOf (c1) + String.valueOf (c2) ' – NomeN

+4

@NomeN: podrías escriba 'new String (new char [] {c1, c2})' –

+2

ad Trivia: las bibliotecas Java SE core no son exactamente una fuente de buen estilo de codificación, eso es bien conocido ;-) –

Respuesta

25

Sus argumentos son buenos; esta es una de las áreas más expresivas del lenguaje Java, y la expresión "" + parece estar muy arraigada, como descubriste.

Ver String concatenation en el JLS.Una expresión como

"" + c1 + c2 

es equivalente a

new StringBuffer().append(new Character(c1).toString()) 
        .append(new Character(c2).toString()).toString() 

excepto que todos los objetos intermedios no son necesarios (por lo que la eficiencia no es un motivo). La especificación dice que una implementación puede usar el StringBuffer o no. Como esta característica está integrada en el lenguaje, no veo ninguna razón para usar la forma más detallada, especialmente en un lenguaje ya detallado.

+7

En realidad, no. El JLS lo explica de esta manera, pero el compilador lo implementa de manera diferente. El Eclipse compilador produce bytecode equivalente a nuevo StringBuilder(). Append (c1) .Append (c2) .toString() El compilador javac (1,5) produce bytecode equivalente a nuevo StringBuilder(). Append ("") .append (c1) .append (c2) .toString() –

2

Creo que en "" + var la + es en realidad sobrecargado para hacer la conversión:

El lenguaje Java proporciona soporte especial para el operador de concatenación de cadenas (+) y para la conversión de otros objetos a cadenas. La concatenación de cadenas se implementa a través de la clase StringBuilder (o StringBuffer) y su método de adición. Las conversiones de cadenas se implementan a través del método toString, definido por Object y heredado por todas las clases en Java. Para obtener información adicional sobre la concatenación de cadenas y la conversión

Así que no hay diferencia y no hay problema desde el punto de vista técnico.

Forma un punto de vista de legibilidad: se trata de una cuestión de preferencia personal o de un estilo de codificación acordado dentro del equipo.

+0

Acabo de agregar la etiqueta [coding-style] al pregunta; de eso se trata principalmente. – polygenelubricants

18

El problema con esa construcción es que generalmente no expresa la intención.

Representa la concatenación de una cadena con otro valor, pero la concatenación no suele ser el objetivo de esta línea.

En el caso específico que ha demostrado, la concatenación es en realidad el objetivo, por lo que este código indica expresar la intención.

En el uso más común de este enfoque (String s = "" + intValue;), la concatenación es simplemente un efecto secundario tolerado, mientras que la conversión de intValue es el objetivo real. Y un simple String.valueOf(intValue) expresa esa intención mucho más clara.

+8

No lo creo. '" "+ x' es extremadamente común, la intención debe ser clara. – mafu

+0

+1 para una buena discusión; todavía estoy en desacuerdo. – polygenelubricants

+8

@mafutrct: si la intención solo está clara cuando has visto esa construcción exacta muchas veces, entonces no está claro como tal. Solo demuestra que el reconocimiento de patrones funciona. –

2

En mi opinión, "" + x es muy legible, corto y preciso al grano. Preferiría construcciones más largas como String.valueOf. El comportamiento está bien definido y es tan común en el uso que me resulta difícil llamarlo un hack en absoluto.

Lo único que me preocupa un poco es el rendimiento, y estoy muy seguro de que no suele importar (aunque no mida ni mire el binario). También hay una buena posibilidad de que este tipo de concat se optimice, ya que debería ser fácil de detectar (aunque esto solo es una suposición).

+0

importa mucho si tu código se ejecuta cientos de miles de veces en un ciclo. – Epaga

+0

Nadie usaría esto en un bucle en los bucles siempre está utilizando el código de rendimiento más conocido. En el 99% de todos los casos, no es un problema. La legibilidad en el caso general es mucho más importante, imo. – mafu

1

A menos que su aplicación necesite cada onza de rendimiento, escriba el código que es más rápido de escribir y más fácil de leer. "" + es una sintaxis más lenta de ejecutar, pero ciertamente parece más fácil de leer cada vez que la utilizo.

2

¿Qué hay de

new String(new char[] {a, b}) 

y si se alot se podría crear una clase "Cuerdas" con:

public static String valueOf(char... chars) { 
    return new String(chars); 
} 

Su línea diría entonces

String s = Strings.valueOf(a, b); 

Niza y corto.

Editado

un mejor nombre podría ser:

String s = Chars.asString(a, b); 
+0

También debería ser muy rápido, ya que lo único que debe hacerse es una copia de matriz que es bastante rápida. – whiskeysierra

+0

esa es una buena alternativa. – Epaga

+0

-1 nadie Puede decir lo que hace sin mirar el método llamado. Por favor refactor! –

4

Yo prefiero usar String.valueOf para individuales conversiones - pero en su caso, usted realmente quiere concatenación.

Sin embargo, sugeriría que esta versión sería eliminar toda posible ambigüedad:

String s = c1 + "" + c2; 

De esa manera no hay posibilidad, aunque remota, de alguien que está considerando si c1 y c2 se sumarán antes de la concatenación.

0

La mejor manera de saber es para compilar/descompilar el código, he utilizado Jad http://en.wikipedia.org/wiki/JAD_(JAva_Decompiler) para eso, se verá que su expresión se convirtió en

cadena s = (new StringBuilder()). Append ("") .append (ci) .append (c2) .toString();

Como se puede ver javac realidad incluido append ("") llamada, pero su costo es insignificante, señalando se adjunta al búfer StringBuilder interna, se puede comprobar la fuente de StringBuilder

1

El estilo "" + var tiene un problema muy grande en mi opinión. Simplemente usa el método toString del var. Entonces, si cambia el tipo de var a otra cosa, no obtendrá una excepción. Un buen ejemplo que acabo de encontrar es que el tipo se cambió de int a Optional<Integer>. El código aún compila bien, pero obtienes un resultado completamente diferente.

Cuestiones relacionadas