78 votes

Primitive de type "court" - casting en Java

J'ai une question sur le type de primitive short en Java. Je suis à l'aide de JDK 1.6.

Si j'ai le texte suivant:

short a = 2;
short b = 3;
short c = a + b;

le compilateur ne veut pas compiler - il dit qu'il "ne peut pas convertir en int court" et me suggère de faire un casting pour short, donc:

short c = (short) (a + b);

fonctionne vraiment. Mais ma question est: pourquoi ai-je besoin de cast? Les valeurs de a et b sont dans la gamme d' short - la gamme de valeurs courtes est {de -32 768, 32767}. J'ai aussi besoin de voter lorsque je veux effectuer les opérations -, *, / (je n'ai pas vérifié pour les autres).

Si je fais la même chose pour le type primitif int, je n'ai pas besoin de jeter aa+bb d' int. Le suivant fonctionne très bien:

int aa = 2;
int bb = 3;
int cc = aa +bb;

J'ai découvert cela lors de la conception d'une classe où j'ai besoin d'ajouter deux variables de type court, et le compilateur a voulu me faire un casting. Si je fais cela avec deux variables de type int, je n'ai pas besoin de cast.

Merci beaucoup à l'avance.

Une petite remarque: la même chose se produit également avec le type de primitive byte. Donc, cela fonctionne:

byte a = 2;
byte b = 3;
byte c = (byte) (a + b);

mais ce n'est pas:

byte a = 2;
byte b = 3;
byte c = a + b;

Pour long, float, double, et int, il n'est pas nécessaire de jeter. Seulement pour short et byte valeurs.

64voto

VonC Points 414372

Comme expliqué en bref C# (mais aussi pour d'autres langues compilateurs ainsi, comme Java)

Il y a un prédéfini conversion implicite de court int, long, float, double, decimal.

Vous ne pouvez pas convertir implicitement non littérale types numériques de grande taille de stockage à court (voir partie Intégrante Types de Table pour les tailles de stockage de types intégraux). Considérons, par exemple, à la suite de deux courts variables x et y:

short x = 5, y = 12;

La suite de l'instruction d'affectation produira une erreur de compilation, en raison de l'expression arithmétique sur le côté droit de l'opérateur d'affectation est évaluée à int par défaut.

short z = x + y;   // Error: no conversion from int to short

Pour résoudre ce problème, utilisez un plâtre:

short z = (short)(x + y);   // OK: explicit conversion

Il est cependant possible d'utiliser les instructions suivantes, où la variable de destination a la même taille de stockage ou une plus grande taille de stockage:

int m = x + y;
long n = x + y;


Une bonne question qui suit est:

"pourquoi une expression arithmétique sur le côté droit de l'opérateur d'affectation est évaluée à int par défaut" ?

Une première réponse peut être trouvée dans:

La classification et Officiellement la Vérification Constante entière Pliage

Le langage Java spécification définit exactement comment les nombres entiers sont représentés et comment l'arithmétique des nombres entiers expressions sont évaluées. C'est une propriété importante de Java comme ce langage de programmation a été conçu pour être utilisé dans des applications distribuées sur Internet. Un programme Java est nécessaire pour produire le même résultat indépendamment de la machine cible de l'exécuter.

En revanche, C (et la majorité des plus largement utilisé impératif et langages de programmation orientée objet) est plus bâclée et laisse de nombreuses caractéristiques importantes de l'ouvrir. L'intention derrière cette inexacte de la langue la spécification est clair. Les mêmes programmes C sont censés fonctionner sur 16 bits, 32-bit, ou même de l'architecture 64 bits par l'instanciation de l'entier de l'arithmétique la source de programmes avec les opérations arithmétiques intégré dans le processeur cible. Cela conduit à beaucoup plus d'un code efficace, car il peut utiliser le disponibles la machine directement. Aussi longtemps que l'entier des calculs de traiter seulement avec des chiffres être "suffisamment petits", des incohérences apparaissent.

En ce sens, le C arithmétique des nombres entiers est un espace réservé qui n'est pas défini exactement par le langage de programmation spécification, mais n'est complètement instancié par la détermination de la machine cible.

Java définit précisément comment les entiers sont représentés et comment l'arithmétique des nombres entiers, est calculé.

      Java Integers
--------------------------
Signed         |  Unsigned
--------------------------
long  (64-bit) |
int   (32-bit) |
short (16-bit) |  char (16-bit)
byte  (8-bit)  |

Chevalier est le seul type entier non signé. Ses valeurs représentent des caractères Unicode, d' \u0000 de \uffff, c'est à dire de 0 à 216-1.

Si un nombre entier opérateur a un opérande de type long, l'autre opérande est également convertie en type long. Sinon, l'opération est effectuée sur des opérandes de type int, si nécessaire, plus courte opérandes sont convertis en int. Les règles de conversion sont exactement spécifié.

[À partir de Notes Électroniques en Informatique Théorique, 82 N ° 2 (2003)
Blesner-Blech-COCV 2003: Sabine GLESNER, Jan Olaf BLECH,
Fakultät für Informatik,
Universität Karlsruhe
Karlsruhe, Allemagne]

17voto

Jon Skeet Points 692016

EDIT: Bon, maintenant on sait que c'est Java...

La Section 4.2.2 de la Java Language Specification états:

Le langage de programmation Java fournit un certain nombre d'opérateurs qui agissent sur partie intégrante des valeurs:

[...]

Le numérique les opérateurs, qui sont le résultat dans une valeur de type int ou long: [...] L'additif opérateurs + et - (§15.18)

En d'autres termes, c'est comme en C# l'opérateur d'addition (lorsqu'il est appliqué à des types intégraux) ne sont toujours que des résultats en int ou long, ce qui est pourquoi vous avez besoin de jeter à attribuer à un short variable.

Origine de la réponse (C#)

En C# (vous n'avez pas spécifié de la langue, donc je suppose), la seule outre, les opérateurs sur les types primitifs sont:

int operator +(int x, int y);
uint operator +(uint x, uint y);
long operator +(long x, long y);
ulong operator +(ulong x, ulong y);
float operator +(float x, float y);
double operator +(double x, double y);

Ceux-ci sont en C# 3.0, section 7.7.4. En outre, l'ajout décimal est défini:

decimal operator +(decimal x, decimal y);

(Énumération outre, la concaténation de chaîne et délégué de la combinaison sont également définis.)

Comme vous pouvez le voir, il n'y a pas d' short operator +(short x, short y) opérateur - si les deux opérandes sont implicitement converti en int et int formulaire est utilisé. Cela signifie que le résultat est une expression de type "int", d'où la nécessité de lancer.

16voto

Rik Points 12802

C# et Java, le arithmatic expression sur le côté droit de la mission évalue à int par défaut. C'est pourquoi vous avez besoin de jeter en arrière pour un court, car il n'y a pas de conversion implicite forme int court, pour des raisons évidentes.

8voto

kdgregory Points 21849

Étant donné que le "pourquoi int par défaut", la question n'a pas été répondu ...

Tout d'abord, "par défaut" n'est pas vraiment le bon terme (bien qu'assez proche). Comme l'a noté VonC, une expression composée d'entiers et de longs aura une longue suite. Et une opération consistant à ints/journaux et doubles aura un double résultat. Le compilateur favorise les conditions d'une expression à tout type offre une plus grande gamme et/ou de précision dans le résultat (à virgule flottante types sont présumés avoir plus de portée et de précision que l'intégrale, bien que vous faire perdre de la précision de la conversion de grandes aspire à double).

Un inconvénient est que cette promotion ne se produit que pour les termes qui en ont besoin. Ainsi dans l'exemple suivant, la sous-expression 5/4 utilise seulement partie intégrante des valeurs et de l'est effectuée à l'aide de math entier, même si l'expression globale implique un double. Le résultat n'est pas ce à quoi vous pourriez vous attendre...

(5/4) * 1000.0

OK, alors pourquoi sont octet et court promus en int? Sans références à l'appui, c'est en raison de l'aspect pratique: il y a un nombre limité de bytecode.

"Bytecode", comme son nom l'indique, utilise un octet pour spécifier une opération. Par exemple iadd, qui ajoute deux ints. Actuellement, 205 opcodes sont définis, et de math entier prend 18 pour chaque type (c'est à dire, un total de 36 entre integer et long), sans compter les opérateurs de conversion.

Si court, et de l'octet chacun a son propre ensemble de opcodes, vous seriez au 241, la limitation de la capacité de la machine à développer. Comme je l'ai dit, pas de références à l'appui, mais je soupçonne que Gosling et al dit "combien de fois avez fait de short?" D'autre part, la promotion de byte int conduit à ce n'est pas si merveilleux effet (la réponse attendue est de 96, le réel est -16):

byte x = (byte)0xC0;
System.out.println(x >> 2);

5voto

Darron Points 13196

Quelle langue utilisez-vous?

Beaucoup de C en fonction de langues ont une règle que toute expression mathématique est effectuée dans la taille des int ou plus. De ce fait, une fois que vous ajoutez deux courts-métrages le résultat est de type int. Cela entraîne la nécessité pour un casting.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X