Pourquoi "int i = 2147483647 + 1;" OK, mais "octet b = 127 + 1;" n'est pas compilable?

126

Pourquoi est-ce int i = 2147483647 + 1;OK, mais byte b = 127 + 1;n'est pas compilable?

goku
la source
16
J'ai aussi un vrai doute: pourquoi le bytetype de données est-il si pénible?!
BoltClock
9
c'est certainement une erreur de conception qui byteest signée au lieu de non signée.
irréputable du
4
@BoltClock C'est seulement une douleur quand vous ne savez pas comment l'utiliser correctement. stackoverflow.com/questions/397867/…
starblue
2
@starblue, y a-t-il un exemple réel où le type d'octet Java est applicable?
Thorbjørn Ravn Andersen
Si des données sont spécifiées sous forme d'octet, utilisez un Java bytepour plus de clarté, par exemple dans les paramètres. Dans ce cas, le fait que vous ne puissiez pas attribuer de intvaleurs détectera même quelques bogues. Ou utilisez bytepour économiser de l'espace dans les tableaux. Je n'utiliserais pas bytepour une valeur unique qui rentre juste dans un octet.
starblue

Réponses:

172

Les constantes sont évaluées comme des ints, donc 2147483647 + 1débordent et vous donnent un nouvel int, qui est assignable à int, tout en étant 127 + 1également évalué comme intégal à 128, et il n'est pas assignable à byte.

MByD
la source
10
En fait, aujourd'hui, j'ai lu quelques énigmes Java , y compris un puzzle à peu près ça ... Voir ici: javapuzzlers.com/java-puzzlers-sampler.pdf - puzzle 3
MByD
3
Le problème est le type intdû à la promotion numérique binaire, la valeur 127est un hareng rouge.
starblue du
Je préférerais que les constantes soient évaluées avec une précision infinie et donnent également une erreur sur int i = 2147483647 + 1;
Eduardo
@MByD: Comme vous l'avez dit " while 127 + 1 also evaluated as int equals to 128, and it is not assignable to byte.", cela signifie-t-il que 50 + 1 seront évalués comme byteet donc assignables byte?
Bhushan
1
@ 10101010 - pas exactement. il sera assignable à byte, mais d'abord (selon la norme) il sera évalué comme int.
MByD
35

Le littéral 127 désigne une valeur de type int. Il en va de même pour le littéral 1. La somme de ces deux est l'entier 128. Le problème, dans le second cas, est que vous l'assignez à une variable de type octet. Cela n'a rien à voir avec la valeur réelle des expressions. Cela a à voir avec Java ne prenant pas en charge les coercitions (*). Vous devez ajouter un transtypage

byte b = (byte)(127 + 1);

puis il compile.

(*) du moins pas du genre String-to-integer, float-to-Time, ... Java prend en charge les coercitions si elles ne sont, en un sens, pas de perte (Java appelle cela "élargissement").

Et non, le mot «coercition» n'avait pas besoin d'être corrigé. Il a été choisi très délibérément et correctement à cela. De la source la plus proche (Wikipédia): "Dans la plupart des langues, le mot coercition est utilisé pour désigner une conversion implicite , soit pendant la compilation, soit pendant l'exécution." et "En informatique, la conversion de type, le transtypage et la coercition sont différentes manières de changer, implicitement ou explicitement, une entité d'un type de données en un autre.".

Erwin Smout
la source
Votre exemple de code devrait probablement être byte b = (byte) 127 + 1; qui est «Ajouter 1 à une valeur d'octet maxed out», votre exemple transforme simplement la valeur int de 128 en une valeur d'octet.
NKCSS
6
@NKCSS - Je ne pense pas que vous ayez raison, ceci - (byte)(127 + 1)transtypez 128 (entier) en octet, tandis que cela (byte)127 + 1transforme le 127 en octet, mais encore une fois en int, car il est ajouté à 1 (int) et vous get 128 (int) et l'erreur reste.
MByD
6

Comme preuve pour @MByD:

Le code suivant se compile:

byte c = (byte)(127 + 1);

Parce que bien que l'expression (127 + 1)soit int et au-delà de la portée hors bytetype, le résultat est converti en byte. Cette expression produit -128.

AlexR
la source
3

Conversion d'affectation JLS3 # 5.2

(variable = expression)

De plus, si l'expression est une expression constante (§15.28) de type byte, short, char ou int:

Une conversion primitive restrictive peut être utilisée si le type de la variable est byte, short ou char, et que la valeur de l'expression constante est représentable dans le type de la variable.


Sans cette clause, nous ne pourrions pas écrire

byte x = 0;
char c = 0;

Mais devrions-nous être capables de faire cela? Je ne pense pas. Il y a pas mal de magie dans la conversion parmi les primitifs, il faut être très prudent. Je ferais de mon mieux pour écrire

byte x = (byte)0;
irréprochable
la source
quant à la question devrions-nous être en mesure de ... je ne vois vraiment rien de mal avec byte x = 0mais là encore, je suis un programmeur C.
Grady Player
Je pourrais peut-être voir un argument contre char c = 0, mais pourquoi l'octet x = 0 est-il faux?
Michael Burge
C'est trompeur pour les yeux non avertis, pensant qu'ils attribuent un octet 0 à une variable d'octet. Pas beaucoup de mal dans cet exemple, mais en général, opérer sur byte / short / char peut être très déroutant en raison de conversions implicites. Ils sont beaucoup plus compliqués qu'on ne le pense. Je veux autant de clarté que possible dans mon code, n'introduisez aucune incertitude dans le but d'enregistrer quelques touches.
irréprochable
Une règle similaire s'applique-t-elle lorsque la conversion primitive de rétrécissement est de long en int, par exemple int i = 1 + 0L? Juste demander parce que votre texte cité exclut explicitement ce cas.
Erwin Smout
@Erwin non, int i=0Lc'est illégal.
irréprochable