La limite de int
est comprise entre -2147483648 et 2147483647.
Si j'entre
int i = 2147483648;
puis Eclipse affichera un soulignement rouge sous "2147483648".
Mais si je fais ça:
int i = 1024 * 1024 * 1024 * 1024;
il compilera très bien.
public class Test {
public static void main(String[] args) {
int i = 2147483648; // error
int j = 1024 * 1024 * 1024 * 1024; // no error
}
}
C'est peut-être une question basique en Java, mais je n'ai aucune idée de la raison pour laquelle la deuxième variante ne produit aucune erreur.
2147483648
: ce littéral n'a aucun sens.Réponses:
Il n'y a rien de mal avec cette déclaration; vous ne faites que multiplier 4 nombres et l'assigner à un entier, il se trouve juste qu'il y a un débordement. Ceci est différent de l'affectation d'un seul littéral , qui serait vérifié par les limites au moment de la compilation.
Il est le hors-limites littérale qui provoque l'erreur, pas la cession :
En revanche, un
long
littéral compilerait bien:Notez qu'en fait, le résultat est toujours calculé au moment de la compilation car il
1024 * 1024 * 1024 * 1024
s'agit d'une expression constante :devient:
Notez que le résultat (
0
) est simplement chargé et stocké et qu'aucune multiplication n'a lieu.De JLS §3.10.1 (merci à @ChrisK pour l'avoir soulevé dans les commentaires):
la source
-1 + 1
, c'est inoffensif; mais car1024^4
cela pourrait aveugler les gens avec des résultats totalement inattendus, loin de ce qu'ils s'attendent à voir. Je pense qu'il devrait y avoir au moins un avertissement ou une note à l'utilisateur, et ne pas l'ignorer silencieusement.1024 * 1024 * 1024 * 1024
et2147483648
n'ont pas la même valeur en Java.En fait,
2147483648
N'EST MÊME PAS UNE VALEUR (bien que ce2147483648L
soit le cas) en Java. Le compilateur ne sait littéralement pas ce que c'est, ni comment l'utiliser. Alors ça gémit.1024
est un entier valide en Java, et un valideint
multiplié par un autre valideint
est toujours un valideint
. Même si ce n'est pas la même valeur que vous attendez intuitivement car le calcul débordera.Exemple
Considérez l'exemple de code suivant:
Vous attendez-vous à ce que cela génère une erreur de compilation? Cela devient un peu plus glissant maintenant.
Et si on mettait une boucle avec 3 itérations et qu'on multipliait dans la boucle?
Le compilateur est autorisé à optimiser, mais il ne peut pas modifier le comportement du programme pendant ce temps.
Quelques informations sur la manière dont ce cas est réellement traité:
En Java et dans de nombreux autres langages, les entiers seront constitués d'un nombre fixe de bits. Les calculs qui ne correspondent pas au nombre de bits donné déborderont ; le calcul est essentiellement effectué module 2 ^ 32 en Java, après quoi la valeur est reconvertie en un entier signé .
D'autres langages ou API utilisent un nombre dynamique de bits (
BigInteger
en Java), lèvent une exception ou définissent la valeur sur une valeur magique telle que not-a-number.la source
2147483648
N'EST MÊME PAS UNE VALEUR (bien qu'elle l'2147483648L
est)", a vraiment cimenté le point que @arshajii essayait de faire valoir.1024 * 1024 * 1024 * 1024
je ne l'ai pas inclus était la suivante: quelle que soit la manière dont cela est traité, je voulais vraiment souligner que ce n'est pas la même chose que l'écriture2147473648
. Il existe de nombreuses façons (et vous en avez énuméré quelques-unes) qu'une langue pourrait potentiellement y faire face. C'est raisonnablement séparé et utile. Alors je vais le laisser. De nombreuses informations deviennent de plus en plus nécessaires lorsque vous avez une réponse de premier ordre à une question populaire.Le comportement que vous suggérez - c'est-à-dire la production d'un message de diagnostic lorsqu'un calcul produit une valeur supérieure à la plus grande valeur pouvant être stockée dans un entier - est une fonctionnalité . Pour que vous puissiez utiliser une fonctionnalité, celle-ci doit être pensée, considérée comme une bonne idée, conçue, spécifiée, implémentée, testée, documentée et livrée aux utilisateurs.
Pour Java, une ou plusieurs des choses de cette liste ne se sont pas produites et vous ne disposez donc pas de la fonctionnalité. Je ne sais pas lequel; vous devrez demander à un concepteur Java.
Pour C #, toutes ces choses se sont produites - il y a environ quatorze ans maintenant - et donc le programme correspondant en C # a produit une erreur depuis C # 1.0.
la source
En plus de la réponse d'Arshajii, je veux montrer une dernière chose:
Ce n'est pas l' affectation qui cause l'erreur mais simplement l'utilisation du littéral . Quand tu essaies
vous remarquerez que cela provoque également une erreur de compilation puisque le côté droit est toujours un
int
-literal et hors de portée.Ainsi, les opérations avec
int
-values (et cela inclut les affectations) peuvent déborder sans erreur de compilation (et sans erreur d'exécution également), mais le compilateur ne peut tout simplement pas gérer ces littéraux trop gros.la source
R: Parce que ce n'est pas une erreur.
Contexte: La multiplication
1024 * 1024 * 1024 * 1024
entraînera un débordement. Un débordement est très souvent un bug. Différents langages de programmation produisent un comportement différent lorsque des débordements se produisent. Par exemple, C et C ++ l'appellent «comportement indéfini» pour les entiers signés, et le comportement est défini sur les entiers non signés (prenez le résultat mathématique, ajoutezUINT_MAX + 1
tant que le résultat est négatif, soustrayezUINT_MAX + 1
tant que le résultat est supérieur àUINT_MAX
).Dans le cas de Java, si le résultat d'une opération avec des
int
valeurs n'est pas dans la plage autorisée, Java ajoute ou soustrait conceptuellement 2 ^ 32 jusqu'à ce que le résultat soit dans la plage autorisée. La déclaration est donc tout à fait légale et non erronée. Cela ne produit tout simplement pas le résultat que vous espériez peut-être.Vous pouvez sûrement vous demander si ce comportement est utile et si le compilateur doit vous avertir. Je dirais personnellement qu'un avertissement serait très utile, mais une erreur serait incorrecte car il s'agit de Java légal.
la source