Pourquoi en Java vous pouvez ajouter des chaînes avec l'opérateur +, alors que String est une classe? Dans le String.java
code, je n'ai trouvé aucune implémentation pour cet opérateur. Ce concept viole-t-il l'orientation de l'objet?
Pourquoi en Java vous pouvez ajouter des chaînes avec l'opérateur +, alors que String est une classe? Dans le String.java
code, je n'ai trouvé aucune implémentation pour cet opérateur. Ce concept viole-t-il l'orientation de l'objet?
Réponses:
Regardons les expressions simples suivantes en Java
int x=15;
String temp="x = "+x;
Le compilateur se convertit "x = "+x;
en un en StringBuilder
interne et utilise .append(int)
pour "ajouter" l'entier à la chaîne.
Tout type peut être converti en type String par conversion de chaîne.
Une valeur x de type primitif T est d'abord convertie en valeur de référence comme si en la donnant comme argument à une expression de création d'instance de classe appropriée (§15.9):
- Si T est booléen, alors utilisez new Boolean (x).
- Si T est un caractère, utilisez le nouveau caractère (x).
- Si T est byte, short ou int, utilisez le nouvel Integer (x).
- Si T est long, utilisez le nouveau Long (x).
- Si T est float, alors utilisez new Float (x).
- Si T est double, utilisez le nouveau Double (x).
Cette valeur de référence est ensuite convertie en type String par conversion de chaîne.
Désormais, seules les valeurs de référence doivent être prises en compte:
- Si la référence est nulle, elle est convertie en la chaîne "null" (quatre caractères ASCII n, u, l, l).
- Sinon, la conversion est effectuée comme si par un appel de la méthode toString de l'objet référencé sans argument; mais si le résultat de l'appel de la méthode toString est nul, alors la chaîne "null" est utilisée à la place.
La méthode toString est définie par la classe primordiale Object (§4.3.2). De nombreuses classes le remplacent, notamment Boolean, Character, Integer, Long, Float, Double et String.
Voir §5.4 pour plus de détails sur le contexte de conversion de chaîne.
Optimisation de la concaténation de chaînes: une implémentation peut choisir d'effectuer la conversion et la concaténation en une seule étape pour éviter de créer puis de supprimer un objet String intermédiaire. Pour augmenter les performances de la concaténation de chaînes répétées, un compilateur Java peut utiliser la classe StringBuffer ou une technique similaire pour réduire le nombre d'objets String intermédiaires créés par l'évaluation d'une expression.
Pour les types primitifs, une implémentation peut également optimiser la création d'un objet wrapper en convertissant directement un type primitif en chaîne.
La version optimisée ne fera pas d'abord une conversion de chaîne complète.
Ceci est une bonne illustration d'une version optimisée utilisée par le compilateur, bien que sans la conversion d'une primitive, où vous pouvez voir le compilateur changer les choses en StringBuilder en arrière-plan:
http://caprazzi.net/posts/java-bytecode-string-concatenation-and-stringbuilder/
Ce code 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();
}
Génère ceci - voyez comment les deux styles de concaténation mènent au même 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
En regardant l'exemple ci-dessus et comment le code d'octet basé sur le code source dans l'exemple donné est généré, vous pourrez remarquer que le compilateur a transformé en interne l'instruction suivante
cip+ciop;
dans
new StringBuilder(cip).append(ciop).toString();
En d'autres termes, l'opérateur +
dans la concaténation de chaînes est en fait un raccourci pour l' StringBuilder
idiome plus verbeux .
C'est la fonction du compilateur Java qui vérifie les opérandes de l' +
opérateur. Et basé sur les opérandes, il génère le code d'octet:
Voici ce que dit la spécification Java :
Les opérateurs + et
-
sont appelés les opérateurs additifs. AdditiveExpression: MultiplicativeExpression AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpressionLes opérateurs additifs ont la même priorité et sont syntaxiquement associatifs à gauche (ils regroupent de gauche à droite). Si le type de l'un ou l'autre des opérandes d'un
+
opérateur estString
, l'opération est une concaténation de chaînes.Sinon, le type de chacun des opérandes de l'
+
opérateur doit être un type convertible (§5.1.8) en un type numérique primitif, sinon une erreur de compilation se produit.Dans tous les cas, le type de chacun des opérandes de l'
-
opérateur binaire doit être un type convertible (§5.1.8) en un type numérique primitif, sinon une erreur de compilation se produit.
Comment la classe String remplace l'opérateur +?
Ce n'est pas le cas. Le compilateur le fait. Strictement parlant, le compilateur surcharge l'opérateur + pour les opérandes String.
Tout d'abord (+) est surchargé et non remplacé
Le langage Java fournit un support spécial pour l'opérateur de concaténation de chaînes (+), qui a été surchargé pour les objets Java Strings.
Si l'opérande de gauche est String, il fonctionne comme une concaténation.
Si l'opérande de gauche est Integer, il fonctionne comme opérateur d'addition
int
et les règles normales de Java s'appliquent.
Le langage Java fournit un support spécial pour l'opérateur de concaténation de chaînes (+) et pour la conversion d'autres objets en chaînes. La concaténation de chaînes est implémentée via la classe StringBuilder
(ou StringBuffer
) et sa append
méthode.
La signification de l' +
opérateur lorsqu'il est appliqué à String
est définie par le langage, comme tout le monde l'a déjà écrit. Puisque vous ne semblez pas trouver cela suffisamment convaincant, considérez ceci:
Les entiers, les flottants et les doubles ont tous des représentations binaires différentes, et donc ajouter deux entiers est une opération différente, en termes de manipulation de bits, que d'ajouter deux flottants: pour les entiers, vous pouvez ajouter petit à petit, en portant un bit et en vérifiant le débordement; pour les flotteurs, vous devez traiter les mantisses et les exposants séparément.
Ainsi, en principe, «l'addition» dépend de la nature des objets «ajoutés». Java le définit pour les chaînes ainsi que pour les entiers et les flottants (longs, doubles, ...)
L' +
opérateur est généralement remplacé par un StringBuilder
au moment de la compilation. Vérifiez cette réponse pour plus de détails à ce sujet.
+
opérateur n'est pas remplacé par StringBuilder
?
+
opérateur Plus ( ) est une fonctionnalité de langage de Java.