¿Por qué en Java puedes agregar Strings con el operador +, cuando String es una clase? En el String.javacódigo no encontré ninguna implementación para este operador. ¿Este concepto viola la orientación a objetos?
El +operador Plus ( ) es una característica del lenguaje de Java.
adatapost
18
Todo es magia del compilador. No se puede hacer la sobrecarga del operador en Java.
León
18
Creo que lo extraño es que String se implementa como una biblioteca fuera del lenguaje (en java.lang.String), pero tiene soporte específico dentro del lenguaje. Eso no está bien.
@ 13ren estás equivocado. La cadena es aparte de la clase java.lang que significa lenguaje: ¡el lenguaje java! Todas las clases en este paquete son especiales. Tenga en cuenta que no necesita importar java.lang para usarlos.
Respuestas:
156
Veamos las siguientes expresiones simples en Java
int x=15;String temp="x = "+x;
Los conversos del compilador "x = "+x;en una StringBuilderinterna 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:
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
newStringBuilder(cip).append(ciop).toString();
En otras palabras, el operador +en la concatenación de cadenas es efectivamente una abreviatura para el StringBuilderlenguaje más detallado .
Muchas gracias, no estoy familiarizado con los códigos de byte jvm, pero generé código para String plus = cip + ciop; y String build = new StringBuilder (cip) .append (ciop) .toString (); son idénticos. y mi pregunta es si esta operación viola la orientación a objetos.
Pooya
77
No lo hace La sobrecarga del operador (como en C ++ y algunos lenguajes) tiene algunos inconvenientes y los diseñadores de Java consideraron que es un concepto algo confuso y lo omitieron de Java. Para mí, un lenguaje orientado a objetos debe tener los conceptos principales de herencia, polimorfismo y encapsulación que tiene Java.
Lion
2
sí, pero creo que este operador se ha sobrecargado para la clase String
Pooya
3
Sí, la sobrecarga del operador se usa en Java para la concatenación del tipo de cadena; sin embargo, no puede definir su propio operador (como en C ++, C # y algunos otros lenguajes).
Lion
55
@Pooya: en realidad "int / int" vs. "int / float" ya está sobrecargado por el operador, por lo que incluso C tiene eso. Sin embargo, lo que C (y Java) no tienen es la sobrecarga del operador definida por el usuario: lo único que define las diferentes formas en que se puede usar un operador (tanto en C como en Java) es la definición del lenguaje (y la distinción se implementa en el compilador). C ++ difiere en que permite la sobrecarga del operador definida por el usuario (que a menudo se denomina simplemente "sobrecarga del operador").
Joachim Sauer
27
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:
Para String, genera código para concatenar cadenas
Para Números, genera código para agregar números.
Esto es lo que dice la especificación de Java :
Los operadores + y -se denominan operadores aditivos. AdditiveExpression: MultiplicativeExpression AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpression
Los 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 es String, 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.
La cita de la especificación no es relevante para esta pregunta en absoluto.
Ernest Friedman-Hill
Este es el extracto "Si el tipo de cualquier operando de un operador + es String, 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 convertible (§5.1.8 ) a un tipo numérico primitivo, o se produce un error en tiempo de compilación ". ¿Me puede decir por qué no es relevante?
Ramesh PVK
77
No dice nada sobre cómo se implementa, que es la pregunta. Creo que el póster ya entiende que la característica existe.
Ernest Friedman-Hill
14
¿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.
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
(2) Si el operando izquierdo es un entero, se desempaqueta automáticamente inty luego se aplican las reglas normales de Java.
Marqués de Lorne
2
Las dos reglas dadas debajo de la cita son incorrectas: creo que deberían ser: dos primitivas (o clases que no se pueden encajonar) = suma; al menos una cadena = concatenación
mwfearnley
4
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 appendmétodo.
El significado del +operador cuando se aplica Stringestá 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, ...)
Si este es el caso, ¿hay alguna razón por la cual StringBuilder existe para uso público? ¿Hay algún caso en el que el +operador no sea reemplazado por StringBuilder?
Cemre
2
La pregunta que desea hacer es "¿por qué el operador + existe para uso público?", Porque esa es la abominación aquí. En cuanto a su otra pregunta, no lo sé exactamente, pero supongo que no existe tal caso.
Escorpio
El compilador podría usar concat () en su lugar, si solo hay dos elementos. Además, el compilador no puede reemplazar concat () con StringBuilder (o usa varios StringBuilders y los agrega juntos) cuando el programador está creando una cadena en código anidado / en bucle largo; usar StringBuilder explícito único será mejor para el rendimiento.
+
operador Plus ( ) es una característica del lenguaje de Java.Respuestas:
Veamos las siguientes expresiones simples en Java
Los conversos del compilador
"x = "+x;
en unaStringBuilder
interna y usos.append(int)
de "añadir" el entero a la cadena.5.1.11. Conversión de cadenas
15.18.1.
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:
Genera esto: vea cómo los dos estilos de concatenación conducen al mismo código de bytes:
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
dentro
En otras palabras, el operador
+
en la concatenación de cadenas es efectivamente una abreviatura para elStringBuilder
lenguaje más detallado .fuente
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 :
fuente
No lo hace. El compilador lo hace. Estrictamente hablando, el compilador sobrecarga el operador + para los operandos String.
fuente
En primer lugar (+) está sobrecargado, no anulado
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
fuente
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
(oStringBuffer
) y suappend
método.fuente
El significado del
+
operador cuando se aplicaString
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, ...)
fuente
El
+
operador generalmente se reemplaza por unStringBuilder
en tiempo de compilación. Verifique esta respuesta para obtener más detalles al respecto.fuente
+
operador no sea reemplazado porStringBuilder
?