web-dev-qa-db-fra.com

Pourquoi les opérateurs d'assignation composés + =, - =, *, = = / = de Java n'ont-ils pas besoin de transtypage?

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)?

3515
Honza Brabec

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 de E1, sauf que E1 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.

2375
Lukas Eder

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'
467
Peter Lawrey

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);
242
Thirler

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

177
Umesh Awasthi

vous devez transtyper de long à intexplicitly 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.

89
dku.rajkumar

Le problème ici concerne le typage.

Lorsque vous ajoutez int et long,

  1. L'objet int est casté à long et les deux sont ajoutés et vous obtenez un objet long.
  2. mais un objet long ne peut pas être implicitement converti en int. Donc, vous devez le faire explicitement.

Mais += est codé de manière à taper le transtypage. i=(int)(i+m)

60
Dinesh Sachdev 108

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

51
tinker_fairy

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
43
Stopfan

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);
21
takra

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+=ji 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é.

11
Gabe Nones

Spécification du langage Java définit _E1 op= E2_ équivalent à E1 = (T) ((E1) op (E2))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é.

2
Konrad Borowski