Java: de ce primesc mesajul de eroare „Type mismatch: nu se poate converti int în byte” (Programare, Java, Conversie De Tip, Byte, Nepotrivire De Tip)

Brad Richards a intrebat.

Dacă declarați variabile de tip byte sau short și încercați să efectuați operații aritmetice pe acestea, primiți mesajul de eroare „Type mismatch: cannot convert int to short” (sau, în mod corespunzător, „Type mismatch: cannot convert int to byte”).

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

În acest exemplu, eroarea de compilare se află pe a treia linie.

Comentarii

  • IIRC, JVM stochează octeți și scurtcircuite ca ints, astfel încât, de obicei, există foarte puține beneficii în utilizarea acestor două tipuri de date. Desigur, îmi dau seama că faceți ceva mult mai complex decât exemplul dvs. și probabil că aveți un motiv foarte bun. –  > Por Dave Webb.
4 răspunsuri
Brad Richards

Deși operatorii aritmetici sunt definiți pentru a opera pe orice tip numeric, conform specificației limbajului Java (5.6.2 Promovarea numerelor binare), operanzii de tip byte și short sunt promovați automat la int înainte de a fi predați operatorilor.

Pentru a efectua operații aritmetice asupra variabilelor de tip byte sau short, trebuie să închideți expresia între paranteze (în interiorul cărora operațiile vor fi efectuate ca fiind de tip int), iar apoi să transformați rezultatul în tipul dorit.

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

Iată o întrebare suplimentară pentru adevărații guru Java: de ce? Tipurile byte și short sunt tipuri numerice foarte bune. De ce Java nu permite operații aritmetice directe pe aceste tipuri? (Răspunsul nu este „pierderea de precizie”, deoarece nu există niciun motiv aparent pentru a converti în int în primul rând).

Actualizare: jrudolph sugerează că acest comportament se bazează pe operațiile disponibile în JVM, mai exact, că sunt implementați doar operatorii de cuvinte întregi și duble. Prin urmare, pentru a opera pe octeți și pantaloni scurți, aceștia trebuie să fie convertiți în int.

Comentarii

  • Bănuiesc că se datorează performanței. În unele unități centrale de procesare, ar putea fi mai costisitor să se utilizeze operanzi mai mici decât registrele cpu. Probabil că a folosit chiar un int de 32 de biți pentru a stoca byte și short, pentru a le păstra aliniate în memorie. –  > Por jassuncao.
  • din moment ce am aflat că – operațiile sunt efectuate în registrele CPU, dar da, sunt aliniate pe 32 de biți. și nici nu poți efectua operatorul + pe caractere -.  > Por bestsss.
  • byte c = (byte)(a + b); după conversie, această expresie va arăta astfel byte c = 57 unde 57 este de tip byte. Dar apoi, deoarece promovarea numerică prevede că toate literalele de tip byte, short și char sunt convertite în int, acest byte 57 va fi promovat în int 57. Deci, în acest sens, compilatorul ar trebui să dea totuși o eroare, dar nu o face. De ce?  > Por user12208242.
David Sykes

Răspunsul la întrebarea dvs. suplimentară este aici:

operanzii de tip byte și short sunt promovați automat în int înainte de a fi predați operatorilor.

Așadar, în exemplul dvs, a și b sunt ambele convertite în int înainte de a fi transmise operatorului +. Rezultatul adunării a două ints este, de asemenea, un an int. Încercarea de a atribui apoi acest rezultat int la un byte provoacă eroarea, deoarece există o posibilă pierdere de precizie. Prin turnarea explicită a rezultatului, îi spuneți compilatorului „Știu ce fac”.

jrudolph

Cred că, problema este că JVM suportă doar două tipuri de valori de stivă: de dimensiunea unui cuvânt și de dimensiunea unui cuvânt dublu.

Apoi, probabil că au decis că ar avea nevoie de o singură operație care să funcționeze cu numere întregi de dimensiune word pe stivă. Deci, există doar iadd, imul și așa mai departe la nivel de bytecode (și nu există operatori pentru bytes și shorts).

Prin urmare, ca rezultat al acestor operații se obține o valoare int, pe care Java nu o poate converti în siguranță înapoi în tipurile de date mai mici byte și short. Astfel, vă forțează să efectuați o cast pentru a reduce valoarea înapoi la byte/short.

Dar, în cele din urmă, aveți dreptate: Acest comportament nu este în concordanță cu cel al inților, de exemplu. Puteți fără probleme să adăugați două ints și să nu primiți nicio eroare dacă rezultatul se supraaglomerează.

Tom Hawtin – tackline

Limbajul Java promovează întotdeauna argumentele operatorilor aritmetici la int, long, float sau double. Să luăm deci expresia:

a + b

unde a și b sunt de tip byte. Aceasta este o prescurtare pentru:

(int)a + (int)b

Această expresie este de tip int. În mod clar, este logic să se afișeze o eroare atunci când se atribuie o valoare int unei variabile byte.

De ce ar fi definit limbajul în acest mod? Să presupunem că a este 60 și b este 70, atunci a+b este -126 – depășire de număr întreg. Ca parte a unei expresii mai complicate care trebuia să aibă ca rezultat un int, acest lucru poate deveni o eroare dificilă. Limitați utilizarea byte și short la stocarea de matrice, constante pentru formate de fișiere/protocoale de rețea și puzzle-uri.

Există o înregistrare interesantă de la JavaPolis 2007. James Gosling dă un exemplu despre cât de complicată este aritmetica fără semn (și de ce nu este în Java). Josh Bloch subliniază faptul că exemplul său dă un exemplu greșit și în cadrul aritmeticii normale cu semn. Pentru o aritmetică inteligibilă, avem nevoie de precizie arbitrară.