Concatenación de cadenas nulas en Java [duplicado]

Resuelto yavoh asked hace 13 años • 5 respuestas

¿Por qué funciona lo siguiente? Esperaría NullPointerExceptionque me arrojaran un.

String s = null;
s = s + "hello";
System.out.println(s); // prints "nullhello"
yavoh avatar Nov 24 '10 03:11 yavoh
Aceptado

¿Por qué debe funcionar?

JLS 5, Sección 15.18.1.1 JLS 8 § 15.18.1 "Operador de concatenación de cadenas +" , que conduce a JLS 8, § 5.1.11 "Conversión de cadenas" , requiere que esta operación se realice correctamente sin fallas:

...Ahora sólo es necesario considerar los valores de referencia. Si la referencia es nula, se convierte en la cadena "nula" (cuatro caracteres ASCII n, u, l, l). De lo contrario, la conversión se realiza como mediante una invocación del método toString del objeto referenciado sin argumentos; pero si el resultado de invocar el método toString es nulo, entonces se utiliza la cadena "null".

¿Como funciona?

¡Veamos el código de bytes! El compilador toma tu código:

String s = null;
s = s + "hello";
System.out.println(s); // prints "nullhello"

y lo compila en código de bytes como si hubiera escrito esto:

String s = null;
s = new StringBuilder(String.valueOf(s)).append("hello").toString();
System.out.println(s); // prints "nullhello"

(Puedes hacerlo tú mismo usando javap -c)

Los métodos de adición de StringBuildertodos manejan nulo muy bien. En este caso, debido a que nulles el primer argumento, String.valueOf()se invoca ya que StringBuilder no tiene un constructor que tome ningún tipo de referencia arbitrario.

Si lo hubiera hecho s = "hello" + sen su lugar, el código equivalente sería:

s = new StringBuilder("hello").append(s).toString();

donde en este caso el método append toma el valor nulo y luego lo delega en String.valueOf().

Nota: La concatenación de cadenas es en realidad uno de los raros lugares donde el compilador decide qué optimización realizar. Como tal, el código "equivalente exacto" puede diferir de un compilador a otro. Esta optimización está permitida por JLS, Sección 15.18.1.2 :

Para aumentar el rendimiento de la concatenación de cadenas repetidas, un compilador de Java puede utilizar la clase StringBuffer o una técnica similar para reducir el número de objetos String intermedios que se crean mediante la evaluación de una expresión.

El compilador que utilicé para determinar el "código equivalente" anterior fue el compilador de Eclipse, ecj .

Mark Peters avatar Nov 23 '2010 20:11 Mark Peters

Consulte las secciones 5.4 y 15.18 de la especificación del lenguaje Java:

La conversión de cadenas se aplica sólo a los operandos del operador binario + cuando uno de los argumentos es una cadena. En este único caso especial, el otro argumento de + se convierte en una Cadena, y una nueva Cadena que es la concatenación de las dos cadenas es el resultado de +. La conversión de cadenas se especifica en detalle en la descripción del operador + concatenación de cadenas.

y

Si solo una expresión de operando es de tipo Cadena, entonces la conversión de cadena se realiza en el otro operando para generar una cadena en tiempo de ejecución. El resultado es una referencia a un objeto String (recién creado, a menos que la expresión sea una expresión constante en tiempo de compilación (§15.28)) que es la concatenación de las dos cadenas de operandos. Los caracteres del operando de la izquierda preceden a los caracteres del operando de la derecha en la cadena recién creada. Si un operando de tipo String es nulo, entonces se utiliza la cadena "null" en lugar de ese operando.

Jonathon Faust avatar Nov 23 '2010 20:11 Jonathon Faust