¿Por qué en Java puedes agregar Strings con el operador +, cuando String es una clase? En el String.java
código no encontré ninguna implementación para este operador. ¿Este concepto viola la orientación a objetos?
¿Por qué en Java puedes agregar Strings con el operador +, cuando String es una clase? En el String.java
código no encontré ninguna implementación para este operador. ¿Este concepto viola la orientación a objetos?
Respuestas:
Veamos las siguientes expresiones simples en Java
int x=15;
String temp="x = "+x;
Los conversos del compilador "x = "+x;
en una StringBuilder
interna y usos .append(int)
de "añadir" el entero a la cadena.
Cualquier tipo se puede convertir a tipo Cadena por conversión de cadena.
Un valor x de tipo primitivo T se convierte primero en 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, utilice el nuevo booleano (x).
- Si T es char, entonces use el nuevo Carácter (x).
- Si T es byte, short o int, use un nuevo entero (x).
- Si T es largo, utilice el nuevo Largo (x).
- Si T es flotante, entonces use el nuevo Flotador (x).
- Si T es doble, entonces use el nuevo Doble (x).
Este valor de referencia luego se convierte al tipo Cadena por conversión de cadena.
Ahora solo se deben considerar los valores de referencia:
- Si la referencia es nula, se convierte a la cadena "nulo" (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 "nulo".
El método toString está definido por la clase primordial Object (§4.3.2). Muchas clases lo anulan, especialmente Boolean, Character, Integer, Long, Float, Double y String.
Ver §5.4 para detalles del contexto de conversión de cadenas.
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 de cadena intermedio. Para aumentar el rendimiento de la concatenación de cadenas repetida, un compilador de Java puede usar la clase StringBuffer o una técnica similar para reducir el número de objetos de cadena intermedios que se crean mediante la evaluación de una expresión.
Para los tipos primitivos, una implementación también puede optimizar la creación de un objeto contenedor mediante la conversión directa de un tipo primitivo a una cadena.
La versión optimizada no realizará primero una conversión de String completa.
Esta es una buena ilustración de una versión optimizada utilizada por el compilador, aunque sin la conversión de una primitiva, donde puede ver el compilador 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 código de bytes:
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.<init>(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.<init>(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
Si observa el ejemplo anterior y cómo se genera el código de byte basado en el código fuente en el ejemplo dado, podrá observar que el compilador ha transformado internamente la siguiente instrucción
cip+ciop;
dentro
new StringBuilder(cip).append(ciop).toString();
En otras palabras, el operador +
en la concatenación de cadenas es efectivamente una abreviatura para el StringBuilder
lenguaje más detallado .
Es la función del compilador de Java que verifica los operandos del +
operador. Y en función de los operandos, genera el código de bytes:
Esto es lo que dice la especificación de Java :
Los operadores + y
-
se denominan operadores aditivos. AdditiveExpression: MultiplicativeExpression AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpressionLos operadores aditivos tienen la misma precedencia y son sintácticamente asociativos a la izquierda (se agrupan de izquierda a derecha). Si el tipo de cualquiera de los operandos de un
+
operador esString
, entonces la operación es la 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 se producirá un error en tiempo de compilació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 producirá un error en tiempo de compilación.
¿Cómo anula la clase String + operador?
No lo hace. El compilador lo hace. Estrictamente hablando, el compilador sobrecarga el operador + para los operandos String.
En primer lugar (+) está sobrecargado, no anulado
El lenguaje Java proporciona soporte especial para el operador de concatenación de cadenas (+), que se ha sobrecargado para los objetos de cadenas Java.
Si el operando del lado izquierdo es String, funciona como concatenación.
Si el operando del lado izquierdo es Entero, funciona como operador de suma
int
y luego se aplican las reglas normales de Java.
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 append
método.
El significado del +
operador cuando se aplica String
está definido por el idioma, como todos ya han escrito. Como no parece encontrar esto suficientemente convincente, considere esto:
Los entrantes, flotantes y dobles tienen representaciones binarias diferentes y, por lo tanto, agregar dos entradas es una operación diferente, en términos de manipulación de bits, que agregar dos flotantes: para las entradas puede agregar bit por bit, transportar un bit y verificar el desbordamiento; para flotadores debes tratar 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 entradas y flotantes (largos, dobles, ...)
El +
operador generalmente se reemplaza por un StringBuilder
en tiempo de compilación. Verifique esta respuesta para obtener más detalles al respecto.
+
operador no sea reemplazado por StringBuilder
?
+
operador Plus ( ) es una característica del lenguaje de Java.