Por que em Java você pode adicionar Strings com o operador +, quando String é uma classe? No String.javacódigo, não encontrei nenhuma implementação para este operador. Esse conceito viola a orientação do objeto?
O +operador Plus ( ) é um recurso de linguagem do Java.
Adatapost
18
É tudo mágico do compilador. Você não pode sobrecarregar o operador em Java.
Lion
18
Eu acho que o mais estranho é que o String é implementado como uma biblioteca fora da linguagem (em java.lang.String), mas possui suporte específico dentro da linguagem. Isso não está certo.
@ 13ren você está errado. String é parte da classe java.lang, que significa idioma - o idioma do java !!! Todas as classes neste pacote são especiais. Observe que você não precisa importar o java.lang para usá-los.
Respostas:
156
Vejamos as seguintes expressões simples em Java
int x=15;String temp="x = "+x;
O compilador converte "x = "+x;em um StringBuilderinternamente 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:
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
newStringBuilder(cip).append(ciop).toString();
Em outras palavras, o operador +na concatenação de strings é efetivamente uma abreviação para o StringBuilderidioma mais detalhado .
Muito obrigado, não estou familiarizado com os códigos de bytes jvm, mas gerou o código para String plus = cip + ciop; e String build = novo StringBuilder (cip) .append (ciop) .toString (); são iguais. e minha pergunta é que esta operação viola a orientação a objetos?
Pooya
7
Não, não faz. A sobrecarga do operador (como em C ++ e em algumas linguagens) tem algumas desvantagens e os designers de Java consideram um conceito um tanto confuso e o omitem do Java. Para mim, uma linguagem orientada a objetos deve ter os principais conceitos de herança, polimorfismo e encapsulamento que o Java possui.
Lion
2
sim, mas acho que esse operador foi sobrecarregado para a classe String
Pooya
3
Sim, a sobrecarga do operador é usada em Java para a concatenação do tipo String. No entanto, você não pode definir seu próprio operador (como em C ++, C # e algumas outras linguagens).
Lion
5
@ Pooya: na verdade, "int / int" vs. "int / float" já está sobrecarregando o operador, então até C tem isso. O que C (e Java), no entanto , não possuem é sobrecarga de operador definida pelo usuário: a única coisa que define as diferentes maneiras pelas quais um operador pode ser usado (em C e Java) é a definição de linguagem (e a distinção é implementada no compilador). O C ++ difere na medida em que permite sobrecarga de operador definida pelo usuário (geralmente chamada de "sobrecarga de operador").
Joachim Sauer
27
É o recurso do compilador Java que verifica os operandos do +operador. E com base nos operandos, gera o código de bytes:
Para String, gera código para concat strings
Para números, ele gera código para adicionar números.
Isto é o que a especificação Java diz :
Os operadores + e -são chamados de operadores aditivos. AdditiveExpression: MultiplicativeExpression AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpression
Os 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 for String, 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.
A citação da especificação não é relevante para esta questão.
Ernest Friedman-Hill
Este é o extrato "Se o tipo de um dos operandos de um operador + for String, a operação será concatenação de strings. Caso contrário, o tipo de cada um dos operandos do operador + deverá ser um tipo conversível (§5.1.8 ) para um tipo numérico primitivo ou ocorre um erro em tempo de compilação ". Você pode me dizer por que não é relevante?
Ramesh PVK
7
Não diz nada sobre como é implementado, qual é a questão. Acho que o pôster já entende que o recurso existe.
Ernest Friedman-Hill
14
Como a classe String substitui + operador?
Não faz. O compilador faz isso. Estritamente falando, o compilador sobrecarrega o operador + para operandos String.
(2) Se o operando esquerdo for um Número Inteiro, ele será retirado da caixa de seleção automática inte as regras normais de Java serão aplicadas.
Marquês de Lorne
2
As duas regras fornecidas abaixo da citação estão erradas: acredito que devam ser: duas primitivas (ou classes unboxable) = adição; pelo menos uma string = concatenação
mwfearnley
4
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 appendmé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, ...)
Se for esse o caso, existe algum motivo pelo qual o StringBuilder exista para uso público? Existem casos em que o +operador não é substituído por StringBuilder?
Cemre
2
A pergunta que você deseja fazer é "por que o operador + existe para uso público?", Porque essa é a abominação aqui. Quanto à sua outra pergunta, não sei exatamente, mas acho que não existe.
Escorpião
O compilador pode usar concat (), se houver apenas dois elementos. Além disso, o compilador falha ao substituir concat () pelo StringBuilder (ou usa vários StringBuilders e os anexa) quando o programador está construindo uma string em um longo código aninhado / em loop - o uso único e explícito de StringBuilder será melhor para o desempenho.
+
operador Plus ( ) é um recurso de linguagem do Java.Respostas:
Vejamos as seguintes expressões simples em Java
O compilador converte
"x = "+x;
em umStringBuilder
internamente e usa.append(int)
para "adicionar" o número inteiro à seqüência de caracteres.5.1.11 Conversão de String
15.18.1
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:
Gera isso - veja como os dois estilos de concatenação levam ao mesmo bytecode:
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
para dentro
Em outras palavras, o operador
+
na concatenação de strings é efetivamente uma abreviação para oStringBuilder
idioma mais detalhado .fonte
É 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 :
fonte
Não faz. O compilador faz isso. Estritamente falando, o compilador sobrecarrega o operador + para operandos String.
fonte
Primeiro de tudo (+) está sobrecarregado, não substituído
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
fonte
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
(ouStringBuffer
) e de seuappend
método.fonte
O significado do
+
operador quando aplicadoString
é 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, ...)
fonte
O
+
operador geralmente é substituído por umStringBuilder
em tempo de compilação. Verifique esta resposta para obter mais detalhes sobre esse assunto.fonte
+
operador não é substituído porStringBuilder
?