2012-12-19 14 views
6

Sto imparando Java. Ho trovato che spesso le espressioni devono essere espresse su un determinato tipo per farlo nel modo giusto. Per esempio, durante la valutazione aritmetica, i byte vengono promossi a numeri interi, quindi la seguente espressione genera un errore:Lettura caratteri in Java

byte b = 10; 
int i; 
i = b*b; //ok, assigning an integer evaluation to an integer variable 
b = b*b; // throws error, coz assigning integer evaluation to byte variable 

Ora, io so che l'assegnazione di un numero intero a una variabile carattere è tutto a posto: char a; a = 88; va bene. Tuttavia, se faccio questo:

char c2 = 'b', c3 = 'c'; 
c2 = c2 + c3; //throws error 
c2 = (char)(c2 + c3); //works fine 

Perché genera un errore quando non viene lanciato? Dopo tutto, il lato destro è ancora un numero intero, quindi l'assegnazione di un intero a una variabile di carattere dovrebbe funzionare correttamente.

+0

'88' è un byte, non solo un numero intero –

risposta

6

In c2 + c3, entrambi gli operandi vengono ampliati implicitamente su int, pertanto il risultato dell'aggiunta è anche int.

JLS §15.18.2. Additive Operators (+ and -) for Numeric Types:

Binary numeric promotion is performed on the operands (§5.6.2).

JLS §5.6.2. Binary Numeric Promotion:

When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:

Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:

  • If either operand is of type double, the other is converted to double.

  • Otherwise, if either operand is of type float, the other is converted to float.

  • Otherwise, if either operand is of type long, the other is converted to long.

  • Otherwise, both operands are converted to type int.

È pertanto finisce con un int. Assegnarlo a una variabile char richiede un cast esplicito.

Tu dici:

Since integer value can be assigned to a character variable...

Solo costanti espressioni intere possono essere assegnati ad una variabile char senza un cast.

JLS §5.2. Assignment Conversion:

In addition, if the expression is a constant expression (§15.28) of type byte, short, char, or int:

  • A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.

Questa conversione automatica restringimento non si applica qui. Hai bisogno di un cast esplicito.

+0

Sì, questo è quello che ho affermato. I caratteri a destra vengono promossi in numeri interi, assegnando così un risultato intero alla variabile a sinistra. Poiché il valore intero può essere assegnato a una variabile di carattere, perché genera un errore? – SexyBeast

+0

+1 per la cosa costante - Non ho trovato il riferimento ;-) – assylias

+0

@Cupidvogel: Non è del tutto corretto. Solo le espressioni * * costanti * sono ristrette automaticamente, e qui non ne guardiamo una. Ho ampliato la risposta. – NPE

3

Non funziona necessariamente correttamente per assegnare un int a un carattere. I caratteri sono solo a 16 bit e gli int sono a 32 bit, quindi potrebbe esserci un overflow.

In generale, Java consente solo l'assegnazione di valori di primitivi senza cast se non è possibile che si verifichi un overflow a causa dell'assegnazione.

+0

Perché ci sarebbe un overflow qui? – SexyBeast

+0

Semplice: prendi due dei più alti valori di char possibili e aggiungili. Questo è un overflow. '('\ uFFFF' + '\ uFFFF')> Character.MAX_VALUE' –

+0

Questo è un po 'una scorciatoia. 'int i = 1; char c = i; 'non verrà compilato anche se non ci sono overflow. – assylias

0

Assegnare un int 88 a un char funziona, perché il compilatore può determinare il valore.

Il caso c2 = c2 + c3 non può essere gestito dal compilatore. Il valore c2 + c3 deve essere valutato in fase di esecuzione. Di conseguenza, il compilatore non può determinare il valore di char effettivo che deve essere assegnato.

1
char c2 = 'b', c3 = 'c'; 
c2 = c2 + c3; //throws error 
c2 = (char)(c2 + c3); //works fine 

quando voi che fate c2+ c3

valore ASCII di questi caratteri si aggiungono, che restituisce un risultato int. quando si assegna il risultato int a char dà errore.

+0

Questo è quello che ho dichiarato, se faccio 'char c = 99;' non genera un errore, perché qui, allora? – SexyBeast

+0

char c = 99; 99 è implicitamente convertito in char. Perché al momento del compilatore il tipo di dati 99 è noto ma il risultato del tipo di ritorno aritmetico dei caratteri non è noto al momento della compilazione. –

0

char è 2 byte e int è 4 byte. Quando scrivi char c = 1; non significa che 1 è int, è solo una costante per javac e javac sa che 1 si inserisce in char. Ma c2 = c2 + c3; è un'operazione aritmetica, javac lo interpreterà come (int)c2 + (int)c3 e questo produce un risultato int. int non si adatta a char quindi javac ti avverte che potrebbe esserci una perdita di precisione.

+0

** char è 2 byte e int è 4 byte. Quando scrivi char c = 1; non significa che 1 è int, è solo una costante per javac e javac sa che 1 si inserisce nel char. ** Come può 1 fir in 'char' quando 1 occupa 4 byte e char 2 byte? – SexyBeast

+0

Attualmente 1 occupa solo 1 byte, è 0x1 e il compilatore sa che si adatta.Ma se hai int i = 1; char c = i; non verrà compilato perché I è un var può essere più lungo di 2 byte –

+0

Quindi stai dicendo che anche se gli interi hanno un'occupazione di spazio predefinita, i letterali interi non si attengono a quello e occupano lo spazio ad hoc? – SexyBeast

0

Dai un'occhiata alla discussione:

Integer arithmetic in Java with char and integer literal

Il motivo sembra essere che "= c2 c2 + c3;" non può essere controllato dal compilatore (viene eseguito in runtime) mentre "char a; a = 88;" è fatto direttamente dal compilatore.

+0

Perché è così? Qual è la differenza tra i compiti? – SexyBeast

+0

È spiegato qui: http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.2 – izaera

+0

Funziona proprio così: se il compilatore può convertire un valore numerico al volo a byte o char lo fa. Se l'assegnazione viene eseguita in runtime, segue altri percorsi di conversione. Prendilo come un'utile utilità per il compilatore o come incoerenza nella lingua (a seconda di quale ti piace di più ;-) – izaera

0

Un esempio per ulteriori chiarimenti:

char c1 = Character.MAX_VALUE; 
char c2 = Character.MAX_VALUE; 
char c3 = (char) (c1 + c2); 
int i3 = c1 + c2; 

System.out.printf("After casting to char: %s, the int value: %s%n", (int) c3, i3); 

Così con colata in realtà abbiamo ottenuto un risultato matematico sbagliato.

0

C'è un certo limite al valore che ogni tipo di base può contenere in java.Assegnare il risultato di un'operazione aritmetica può produrre un risultato imprevedibile in fase di esecuzione, che JVM non è sicuro se il carattere può contenere, quindi il valore errore di compilazione.