Jusqu'à aujourd'hui, je pensais que par exemple:
i += j;
Était juste un raccourci pour:
i = i + j;
Mais si nous essayons ceci:
int i = 5;
long j = 8;
Alors i = i + j;
ne compilera pas mais i += j;
compilera bien.
Cela signifie-t-il qu'en fait i += j;
est un raccourci pour quelque chose comme ceci i = (type of i) (i + j)
?
Comme toujours avec ces questions, le JLS détient la réponse. Dans ce cas §15.26.2 Opérateurs d'assignation composée . Un extrait:
Une expression d'affectation composée de la forme
E1 op= E2
équivaut àE1 = (T)((E1) op (E2))
, oùT
est le type deE1
, sauf queE1
n'est évalué qu'une fois.
Un exemple cité de §15.26.2
[...] le code suivant est correct:
short x = 3; x += 4.6;
et donne x avec la valeur 7 car elle est équivalente à:
short x = 3; x = (short)(x + 4.6);
En d'autres termes, votre hypothèse est correcte.
Un bon exemple de ce casting utilise * = ou/=
byte b = 10;
b *= 5.7;
System.out.println(b); // prints 57
ou
byte b = 100;
b /= 2.5;
System.out.println(b); // prints 40
ou
char ch = '0';
ch *= 1.1;
System.out.println(ch); // prints '4'
ou
char ch = 'A';
ch *= 1.5;
System.out.println(ch); // prints 'a'
Très bonne question. Le spécification du langage Java confirme votre suggestion.
Par exemple, le code suivant est correct:
short x = 3; x += 4.6;
et donne x avec la valeur 7 car elle est équivalente à:
short x = 3; x = (short)(x + 4.6);
Oui,
essentiellement lorsque nous écrivons
i += l;
le compilateur convertit cela en
i = (int)(i + l);
Je viens de vérifier le code du fichier .class
.
Vraiment une bonne chose à savoir
vous devez transtyper de long
à int
explicitly
dans le cas de i = i + l
, la compilation et le résultat seront corrects. comme
i = i + (int)l;
ou
i = (int)((long)i + l); // this is what happens in case of += , dont need (long) casting since upper casting is done implicitly.
mais dans le cas de +=
, cela fonctionne simplement, car l'opérateur effectue implicitement le transtypage de type de type de variable à droite sur type de variable de gauche; il n'est donc pas nécessaire de lancer explicitement le transtypage.
Le problème ici concerne le typage.
Lorsque vous ajoutez int et long,
Mais +=
est codé de manière à taper le transtypage. i=(int)(i+m)
En Java, les conversions de type sont effectuées automatiquement lorsque le type de l'expression situé à droite d'une opération d'affectation peut être promu en toute sécurité au type de la variable situé à gauche de l'affectation. Ainsi, nous pouvons assigner en toute sécurité:
octet -> court -> int -> long -> float -> double.
La même chose ne fonctionnera pas dans l'autre sens. Par exemple, nous ne pouvons pas convertir automatiquement un long en un int car le premier nécessite plus de stockage que le second et par conséquent, des informations peuvent être perdues. Pour forcer une telle conversion, nous devons procéder à une conversion explicite.
Type - Conversion
Parfois, une telle question peut être posée lors d'un entretien.
Par exemple, lorsque vous écrivez:
int a = 2;
long b = 3;
a = a + b;
il n'y a pas de conversion automatique. En C++, il n'y aura aucune erreur lors de la compilation du code ci-dessus, mais en Java, vous obtiendrez quelque chose comme Incompatible type exception
.
Donc, pour l'éviter, vous devez écrire votre code comme ceci:
int a = 2;
long b = 3;
a += b;// No compilation error or any exception due to the auto typecasting
La principale différence est que, avec a = a + b
, il n'y a pas de conversion de type et le compilateur se fâche contre vous pour ne pas avoir transtypé. Mais avec a += b
, il s’agit en réalité de convertir b
en un type compatible avec a
. Donc si tu le fais
int a=5;
long b=10;
a+=b;
System.out.println(a);
Ce que vous faites vraiment, c'est:
int a=5;
long b=10;
a=a+(int)b;
System.out.println(a);
Point subtil ici ...
Il existe une conversion implicite de caractères pour i+j
lorsque j
est un double et i
est un int. Java TOUJOURS convertit un entier en double lorsqu'il existe une opération entre eux.
Pour clarifier i+=j
où i
est un entier et j
est un double peut être décrit comme
i = <int>(<double>i + j)
Voir: cette description du casting implicite
Vous voudrez peut-être transtyper j
en (int)
dans ce cas pour plus de clarté.
Spécification du langage Java définit _E1 op= E2
_ équivalent à E1 = (T) ((E1) op (E2))
où T
est un type de _E1
_ et _E1
_ est évalué une fois .
C'est une réponse technique, mais vous vous demandez peut-être pourquoi. Bien, considérons le programme suivant.
_public class PlusEquals {
public static void main(String[] args) {
byte a = 1;
byte b = 2;
a = a + b;
System.out.println(a);
}
}
_
Qu'est-ce que ce programme imprime?
Avez-vous deviné 3? Dommage, ce programme ne compilera pas. Pourquoi? Eh bien, il se trouve que l’ajout d’octets dans Java est défini pour renvoyer un int
. C’est, je crois, parce que la machine virtuelle Java ne définit pas les opérations sur les octets pour enregistrer les octets (il y en a un nombre limité, après tout), utiliser plutôt des opérations sur les entiers est un détail la langue.
Mais si _a = a + b
_ ne fonctionne pas, cela signifierait que _a += b
_ ne fonctionnerait jamais pour les octets si _E1 += E2
_ était défini comme étant _E1 = E1 + E2
_. Comme le montre l'exemple précédent, ce serait effectivement le cas. En tant qu'opérateur pour faire fonctionner l'opérateur _+=
_ pour les octets et les courts-métrages, une conversion implicite est impliquée. Ce n’est pas si terrible, mais au cours du travail de Java 1.0, l’objectif était de commencer par la publication du langage. En raison de la compatibilité ascendante, ce hack introduit dans Java 1.0 n'a pas pu être supprimé.