Java: pourquoi le message d'erreur «Incompatibilité de type: impossible de convertir int en octet»

StackOverflow https://stackoverflow.com/questions/81392

Question

Si vous déclarez des variables de type octet ou short et tentez d'effectuer des opérations arithmétiques sur celles-ci, le message d'erreur "Erreur de correspondance de type: impossible de convertir int en short" (ou en conséquence, "Type mismatch: impossible de convertir int en octet").

byte a = 23;
byte b = 34;
byte c = a + b;

Dans cet exemple, l'erreur de compilation est sur la troisième ligne.

Était-ce utile?

La solution

Bien que les opérateurs arithmétiques soient définis pour fonctionner sur tout type numérique, conformément à la spécification du langage Java (5.6.2 Promotion numérique binaire), les opérandes de type octet et short sont automatiquement promus en int avant d'être remis aux opérateurs.

Pour effectuer des opérations arithmétiques sur des variables de type octet ou short, vous devez placer l'expression entre parenthèses (à l'intérieur de laquelle les opérations seront effectuées sous la forme type int), puis rediriger le résultat vers le type souhaité.

byte a = 23;
byte b = 34;
byte c = (byte) (a + b);

Voici une question qui fait suite aux vrais gourous de Java: pourquoi? Les types octet et short sont des types parfaitement numériques. Pourquoi Java n'autorise-t-il pas d'opérations arithmétiques directes sur ces types? (La réponse n’est pas la "perte de précision", car il n’ya aucune raison apparente de se convertir à int en premier lieu.)

Mise à jour: jrudolph suggère que ce comportement est basé sur les opérations disponibles dans la machine virtuelle Java, en particulier que seuls les opérateurs de mots complets et doubles sont implémentés. Par conséquent, pour les opérateurs sur les octets et les courts-circuits, ils doivent être convertis en int.

Autres conseils

La réponse à votre question de suivi est la suivante:

  

les opérandes de type octet et short sont automatiquement promus en int avant d'être remis aux opérateurs

Ainsi, dans votre exemple, a et b sont tous deux convertis en un int avant d'être remis à l'opérateur +. Le résultat de l’ajout de deux int est également un int . Essayer d’affecter ensuite ce int à une valeur octet provoque l’erreur en raison du risque de perte de précision. En exprimant explicitement le résultat, vous dites au compilateur "Je sais ce que je fais".

Je pense que le fait est que la machine virtuelle Java ne prend en charge que deux types de valeurs de pile: la taille d'un mot et la taille d'un double mot.

Ensuite, ils ont probablement décidé qu’ils n’auraient besoin que d’une opération qui fonctionnerait sur des entiers de la taille d’un mot de la pile. Il n’ya donc que iadd, imul et ainsi de suite au niveau du bytecode (et aucun opérateur pour les octets et les shorts).

Vous obtenez donc une valeur int à la suite de ces opérations que Java ne peut pas reconvertir en toute sécurité en octets plus petits et en types de données courts. Ils vous obligent donc à utiliser le casting pour réduire la valeur en octet / short.

Mais au final, vous avez raison: ce comportement n’est pas cohérent avec le comportement de ints, par exemple. Vous pouvez sans problème ajouter deux ints et ne pas avoir d'erreur si le résultat déborde.

Le langage Java privilégie toujours les arguments des opérateurs arithmétiques à int, long, float ou double. Alors prenons l'expression:

a + b

où a et b sont de type octet. Ceci est un raccourci pour:

(int)a + (int)b

Cette expression est de type int. Il est clairement logique de donner une erreur lors de l'attribution d'une valeur int à une variable d'octet.

Pourquoi le langage serait-il défini de cette manière? Supposons que a soit 60 et b 70, puis a + b est -126 - dépassement d'entier. En tant qu’élément d’une expression plus complexe qui devrait aboutir à un int, cela peut devenir un bug difficile. Limitez l’utilisation de stockage octet et court-circuit, de constantes pour les formats de fichier / protocoles réseau et des casse-tête.

Il existe un enregistrement intéressant de JavaPolis 2007. James Gosling donne un exemple de la complexité de l’arithmétique non signée (et de la raison pour laquelle elle n’est pas en Java). Josh Bloch fait remarquer que son exemple donne également le mauvais exemple en arithmétique signée normale. Pour l'arithmétique compréhensible, nous avons besoin d'une précision arbitraire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top