¿Cómo reemplaza la clase String al operador +?

¿Por qué en Java puede agregar cadenas con el operador + cuando String es una clase? En el código String.java no encontré ninguna implementación para este operador. ¿Este concepto viola la orientación del objeto?

Veamos las siguientes expresiones simples en Java

 int x=15; String temp="x = "+x; 

El comstackdor convierte "x = "+x; en un StringBuilder internamente y usa .append(int) para “agregar” el entero a la cadena.

5.1.11. Conversión de cadena

Cualquier tipo se puede convertir a tipo de cadena por conversión de cadena.

Un valor x del tipo primitivo T se convierte primero a un valor de referencia como si lo diera como argumento a una expresión de creación de instancia de clase apropiada (§15.9):

  • Si T es booleano, entonces use un nuevo booleano (x).
  • Si T es char, entonces use el nuevo carácter (x).
  • Si T es byte, corto o int, entonces use un nuevo entero (x).
  • Si T es largo, entonces use nuevo Largo (x).
  • Si T es flotante, entonces use Flotante nuevo (x).
  • Si T es doble, entonces use la nueva Doble (x).

Este valor de referencia se convierte a tipo de cadena por conversión de cadena.

Ahora solo deben tenerse en cuenta 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 si fuera 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 usa la cadena “null” en su lugar.

El método toString está definido por el objeto de la clase primordial (§4.3.2). Muchas clases lo anulan, notablemente Boolean, Character, Integer, Long, Float, Double y String.

Ver §5.4 para detalles del contexto de conversión de cadenas.

15.18.1.

Optimización de la concatenación de cadenas: una implementación puede optar por realizar la conversión y la concatenación en un solo paso para evitar crear y luego descartar un objeto String intermedio. Para boost el rendimiento de la concatenación repetida de cadenas, un comstackdor Java puede usar 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.

Para tipos primitivos, una implementación también puede optimizar la creación de un objeto contenedor convirtiendo directamente de un tipo primitivo a una cadena.

La versión optimizada en realidad no realizará una conversión de String completa.

Esta es una buena ilustración de una versión optimizada utilizada por el comstackdor, aunque sin la conversión de una primitiva, donde se puede ver el comstackdor cambiando las cosas en un StringBuilder en segundo plano:

http://caprazzi.net/posts/java-bytecode-string-concatenation-and-stringbuilder/


Este código de Java:

 public static void main(String[] args) { String cip = "cip"; String ciop = "ciop"; String plus = cip + ciop; String build = new StringBuilder(cip).append(ciop).toString(); } 

Genera esto: vea cómo los dos estilos de concatenación conducen al mismo bytecode:

  L0 LINENUMBER 23 L0 LDC "cip" ASTORE 1 L1 LINENUMBER 24 L1 LDC "ciop" ASTORE 2 // cip + ciop L2 LINENUMBER 25 L2 NEW java/lang/StringBuilder DUP ALOAD 1 INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String; INVOKESPECIAL java/lang/StringBuilder.(Ljava/lang/String;)V ALOAD 2 INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder; INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String; ASTORE 3 // new StringBuilder(cip).append(ciop).toString() L3 LINENUMBER 26 L3 NEW java/lang/StringBuilder DUP ALOAD 1 INVOKESPECIAL java/lang/StringBuilder.(Ljava/lang/String;)V ALOAD 2 INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder; INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String; ASTORE 4 L4 LINENUMBER 27 L4 RETURN 

Al observar el ejemplo anterior y cómo se genera el código de bytes basado en el código fuente en el ejemplo dado, podrá observar que el comstackdor ha transformado internamente la siguiente statement

 cip+ciop; 

dentro

 new StringBuilder(cip).append(ciop).toString(); 

En otras palabras, el operador + en la concatenación de cadenas es efectivamente una abreviatura de la expresión más detallada de StringBuilder .

Es la característica del comstackdor de Java que verifica los operandos del operador + . Y basado en los operandos, genera el código de bytes:

  • Para String, genera código para concat string
  • Para Numbers, genera código para agregar números.

Esto es lo que dice la especificación de Java :

Los operadores + y - se llaman operadores aditivos. AdditiveExpression: MultiplicativeExpression AdditiveExpression + MultiplicativeExpression AdditiveExpression – MultiplicativeExpression

Los operadores aditivos tienen la misma precedencia y se asocian sintácticamente a la izquierda (se agrupan de izquierda a derecha). Si el tipo de operando de un operador + es String , entonces la operación es concatenación de cadenas.

De lo contrario, el tipo de cada uno de los operandos del operador + debe ser un tipo que sea convertible (§5.1.8) a un tipo numérico primitivo o que se produzca un error en tiempo de comstackción.

En todos los casos, el tipo de cada uno de los operandos del operador binario debe ser un tipo que sea convertible (§5.1.8) a un tipo numérico primitivo, o se produzca un error en tiempo de comstackción.

¿Cómo la clase String anula + operador?

No es así El comstackdor lo hace Estrictamente hablando, el comstackdor sobrecarga el operador + para los operandos de Cadena.

En primer lugar (+) está sobrecargado, no anulado

El lenguaje Java proporciona soporte especial para el operador de concatenación de cadenas (+), que ha sido sobrecargado para objetos de cadenas de Java.

  1. Si el operando del lado izquierdo es String, funciona como concatenación.

  2. Si el operando del lado izquierdo es Integer, funciona como operador adicional

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 append .

El significado del operador + cuando se aplica a String está definido por el idioma, ya que todos ya lo han escrito. Como no parece encontrar esto suficientemente convincente, considere esto:

Ints, floats y dobles tienen diferentes representaciones binarias, y por lo tanto agregar dos ints es una operación diferente, en términos de manipulación de bits, que agregar dos flotantes: para las entradas se puede agregar bit a bit, llevar un bit y verificar el desbordamiento; para las carrozas debes lidiar con las mantisas y exponentes por separado.

Entonces, en principio, la “adición” depende de la naturaleza de los objetos que se “agregan”. Java lo define para cadenas, así como para ints y flotantes (longs, dobles, …)

El operador + generalmente se reemplaza por un StringBuilder en tiempo de comstackción. Verifique esta respuesta para más detalles sobre ese asunto.