Por que em Java você pode adicionar Strings com o operador +, quando String é uma classe? No String.java
código, não encontrei nenhuma implementação para este operador. Esse conceito viola a orientação do objeto?
Por que em Java você pode adicionar Strings com o operador +, quando String é uma classe? No String.java
código, não encontrei nenhuma implementação para este operador. Esse conceito viola a orientação do objeto?
Respostas:
Vejamos as seguintes expressões simples em Java
int x=15;
String temp="x = "+x;
O compilador converte "x = "+x;
em um StringBuilder
internamente e usa .append(int)
para "adicionar" o número inteiro à seqüência de caracteres.
Qualquer tipo pode ser convertido no tipo String por conversão de string.
Um valor x do tipo primitivo T é primeiro convertido em um valor de referência como se fosse fornecido como argumento para uma expressão de criação de instância de classe apropriada (§15.9):
- Se T for booleano, use o novo booleano (x).
- Se T for char, use o novo caractere (x).
- Se T for byte, curto ou int, use o novo número inteiro (x).
- Se T for longo, use o novo Longo (x).
- Se T for flutuante, use o novo flutuador (x).
- Se T for o dobro, use o novo Duplo (x).
Esse valor de referência é então convertido para o tipo String por conversão de string.
Agora, apenas os valores de referência precisam ser considerados:
- Se a referência for nula, ela será convertida na cadeia "nula" (quatro caracteres ASCII n, u, l, l).
- Caso contrário, a conversão é executada como se por uma invocação do método toString do objeto referenciado sem argumentos; mas se o resultado da chamada do método toString for nulo, a sequência "null" será usada.
O método toString é definido pela classe primordial Object (§4.3.2). Muitas classes o substituem, especialmente Boolean, Character, Inteiro, Long, Float, Double e String.
Veja §5.4 para detalhes do contexto de conversão de strings.
Otimização da concatenação de strings: uma implementação pode optar por executar a conversão e concatenação em uma etapa para evitar a criação e o descarte de um objeto String intermediário. Para aumentar o desempenho da concatenação de seqüência de caracteres repetida, um compilador Java pode usar a classe StringBuffer ou uma técnica semelhante para reduzir o número de objetos String intermediários criados pela avaliação de uma expressão.
Para tipos primitivos, uma implementação também pode otimizar a criação de um objeto wrapper, convertendo diretamente de um tipo primitivo em uma sequência.
A versão otimizada, na verdade, não fará uma conversão completa de String primeiro.
Esta é uma boa ilustração de uma versão otimizada usada pelo compilador, embora sem a conversão de uma primitiva, onde você pode ver o compilador mudando as coisas para um StringBuilder em segundo plano:
http://caprazzi.net/posts/java-bytecode-string-concatenation-and-stringbuilder/
Este código 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();
}
Gera isso - veja como os dois estilos de concatenação levam ao mesmo 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.<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
Observando o exemplo acima e como o código de bytes baseado no código-fonte no exemplo fornecido é gerado, você poderá perceber que o compilador transformou internamente a seguinte instrução
cip+ciop;
para dentro
new StringBuilder(cip).append(ciop).toString();
Em outras palavras, o operador +
na concatenação de strings é efetivamente uma abreviação para o StringBuilder
idioma mais detalhado .
É o recurso do compilador Java que verifica os operandos do +
operador. E com base nos operandos, gera o código de bytes:
Isto é o que a especificação Java diz :
Os operadores + e
-
são chamados de operadores aditivos. AdditiveExpression: MultiplicativeExpression AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpressionOs operadores aditivos têm a mesma precedência e são sintaticamente associados à esquerda (eles agrupam da esquerda para a direita). Se o tipo de um operando de um
+
operador forString
, a operação será concatenação de cadeia de caracteres.Caso contrário, o tipo de cada um dos operandos do
+
operador deve ser um tipo conversível (§5.1.8) em um tipo numérico primitivo, ou ocorrerá um erro em tempo de compilação.Em todos os casos, o tipo de cada um dos operandos do
-
operador binário deve ser um tipo conversível (§5.1.8) em um tipo numérico primitivo ou ocorrerá um erro em tempo de compilação.
Como a classe String substitui + operador?
Não faz. O compilador faz isso. Estritamente falando, o compilador sobrecarrega o operador + para operandos String.
Primeiro de tudo (+) está sobrecarregado, não substituído
A linguagem Java fornece suporte especial para o operador de concatenação de cadeias (+), que foi sobrecarregado para objetos Java Strings.
Se o operando do lado esquerdo for String, ele funcionará como concatenação.
Se o operando do lado esquerdo for Inteiro, ele funcionará como operador de adição
int
e as regras normais de Java serão aplicadas.
A linguagem Java fornece suporte especial para o operador de concatenação de cadeias (+) e para a conversão de outros objetos em cadeias. A concatenação de cadeias é implementada através da classe StringBuilder
(ou StringBuffer
) e de seu append
método.
O significado do +
operador quando aplicado String
é definido pelo idioma, como todos já escreveram. Como você não acha isso suficientemente convincente, considere o seguinte:
Ints, floats e doubles têm representações binárias diferentes e, portanto, adicionar duas entradas é uma operação diferente, em termos de manipulação de bits, do que adicionar duas entradas flutuantes: Para entradas, você pode adicionar pouco a pouco, carregando um pouco e verificando se há excesso; para carros alegóricos, você deve lidar com as mantissas e expoentes separadamente.
Portanto, em princípio, "adição" depende da natureza dos objetos que estão sendo "adicionados". Java define para Strings, bem como ints e floats (longs, doubles, ...)
O +
operador geralmente é substituído por um StringBuilder
em tempo de compilação. Verifique esta resposta para obter mais detalhes sobre esse assunto.
+
operador não é substituído por StringBuilder
?
+
operador Plus ( ) é um recurso de linguagem do Java.