Perché è "int i = 2147483647 + 1;" OK, ma "byte b = 127 + 1;" non è compilabile?


126

Perché è int i = 2147483647 + 1;OK, ma byte b = 127 + 1;non è compilabile?


16
Ho anche un vero dubbio: perché il bytetipo di dati è così doloroso ?!
BoltClock

9
è sicuramente un errore di progettazione che byteviene firmato anziché non firmato.
indiscutibile il

4
@BoltClock È solo un dolore quando non sai come usarlo correttamente. stackoverflow.com/questions/397867/...
starblue

2
@starblue, c'è qualche esempio di vita reale in cui è applicabile il tipo di byte Java?
Thorbjørn Ravn Andersen,

Se ci sono dati che sono specificati come byte, utilizzare un Java byteper chiarezza, ad esempio nei parametri. In tal caso, il fatto che non sia possibile assegnare intvalori catturerà anche alcuni bug. Oppure utilizzare byteper risparmiare spazio nelle matrici. Non userei byteper un singolo valore che si adatta a un byte.
Starblue

Risposte:


172

Le costanti vengono valutate come ints, quindi 2147483647 + 1trabocca e ti dà un nuovo int, che è assegnabile a int, mentre 127 + 1valutato anche come intuguale a 128, e non è assegnabile a byte.


10
In realtà, oggi ho letto alcuni enigmi Java , tra cui un puzzle proprio a questo proposito ... Vedi qui: javapuzzlers.com/java-puzzlers-sampler.pdf - puzzle 3
MByD

3
Il problema è il tipo intdovuto alla promozione numerica binaria, il valore 127è un'aringa rossa.
Starblue

Preferirei che le costanti venissero valutate con precisione infinita e che fornissero anche un errore su int i = 2147483647 + 1;
Eduardo,

@MByD: Come hai detto " while 127 + 1 also evaluated as int equals to 128, and it is not assignable to byte.", questo significa che 50 + 1 saranno valutati come bytee quindi sono assegnabili a byte?
Bhushan,

1
@ 10101010 - non esattamente. sarà assegnabile a byte, ma prima (secondo lo standard) verrà valutato come int.
MByD,

35

Il valore letterale 127 indica un valore di tipo int. Lo stesso vale per il letterale 1. La somma di questi due è il numero intero 128. Nel secondo caso, il problema è che lo si sta assegnando a una variabile di tipo byte. Non ha nulla a che fare con il valore reale delle espressioni. Ha a che fare con Java che non supporta le coercizioni (*). Devi aggiungere un typecast

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

e quindi si compila.

(*) almeno non del tipo String-to-integer, float-to-Time, ... Java supporta le coercizioni se sono, in un certo senso, non-loss (Java chiama questo "allargamento").

E no, la parola "coercizione" non ha bisogno di essere corretta. È stato scelto molto deliberatamente e correttamente. Dalla fonte più vicina alla mano (Wikipedia): "Nella maggior parte delle lingue, la parola coercizione viene utilizzata per indicare una conversione implicita , sia durante la compilazione che durante il runtime." e "Nell'informatica, la conversione dei tipi, la tipografia e la coercizione sono modi diversi di, implicitamente o esplicitamente, cambiare un'entità di un tipo di dati in un altro".


Il tuo esempio di codice dovrebbe probabilmente essere byte b = (byte) 127 + 1; che è "Aggiungi 1 a un valore di byte massimo", il tuo esempio trasforma il valore int di 128 in un valore di byte.
NKCSS

6
@NKCSS - Non penso che tu abbia ragione, questo - (byte)(127 + 1)cast 128 (intero) su un byte, mentre questo (byte)127 + 1lancia il 127 su un byte, ma poi di nuovo su un int, poiché è aggiunto a 1 (int) e tu ottiene 128 (int) e l'errore rimane.
MByD

6

A riprova di @MByD:

Il seguente codice viene compilato:

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

Perché sebbene expression (127 + 1)sia int e al di là dell'ambito off bytetype, il risultato viene trasmesso byte. Questa espressione produce -128.


3

Conversione assegnazione JLS3 # 5.2

(variabile = espressione)

Inoltre, se l'espressione è un'espressione costante (§15.28) di tipo byte, short, char o int:

Una conversione primitiva restrittiva può essere utilizzata se il tipo di variabile è byte, breve o char e il valore dell'espressione costante è rappresentabile nel tipo di variabile.


Senza questa clausola, non saremmo in grado di scrivere

byte x = 0;
char c = 0;

Ma dovremmo essere in grado di farlo? Io non la penso così. Ci sono alcune magie in corso nella conversione tra i primitivi, bisogna stare molto attenti. Vorrei fare del mio meglio per scrivere

byte x = (byte)0;

per quanto riguarda la domanda dovremmo essere in grado di ... non vedo davvero nulla di sbagliato in questo, byte x = 0ma poi di nuovo, sono un programmatore C.
Grady Player

Potrei forse vedere un argomento contro char c = 0, ma perché byte x = 0 è sbagliato?
Michael Burge,

È fuorviante per gli occhi non allenati, pensando che stiano assegnando un byte 0 a una variabile byte. Non molto male in questo esempio, ma in generale, operare su byte / short / char potrebbe diventare molto confuso a causa di conversioni implicite. Sono molto più complicati di quanto la gente possa pensare. Voglio quanta più chiarezza possibile nel mio codice, non introdurre alcuna incertezza per salvare qualche colpo di chiave.
irreversibile

Una regola simile si applica quando la conversione primitiva restrittiva va da long a int, ad esempio int i = 1 + 0L? Chiedo solo perché il testo citato esclude esplicitamente quel caso.
Erwin Smout,

@Erwin no, int i=0Lè illegale.
irreputabile
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.