2011-12-31 6 views
59

Quando si aggiunge 'a' + 'b', ne viene prodotto 195. Il tipo di dati di uscita è char o int?In Java, il risultato dell'aggiunta di due caratteri è int o char?

+2

Se il tipo fosse 'char' allora il valore del' 'un' + 'b'' non sarebbe '195' ma'' Ã'' – Joren

+1

si tratta di 195 qui - http://ideone.com ma non in Eclipse. – orange

+2

Hai letto che dal libro Algorithms lol! Sono venuto qui proprio per questo esercizio;) –

risposta

108

Il risultato della somma caratteri Java, pantaloncini, o byte è un int:

Java Language Specification on Binary Numeric Promotion:

  • Se uno qualsiasi degli operandi è di un tipo di riferimento, conversione unboxing (§5.1.8) viene eseguita. Quindi:
  • Se uno degli operandi è di tipo double, l'altro viene convertito in double.
  • Altrimenti, se uno degli operandi è di tipo float, l'altro viene convertito in float.
  • In caso contrario, se uno degli operandi è di tipo lungo, l'altro viene convertito in long.
  • In caso contrario, entrambi gli operandi vengono convertiti in tipo int.

But note what it says about compound assignment operators (like +=):

Il risultato dell'operazione binaria viene convertito nel tipo di variabile di sinistra ... e il risultato della conversione è memorizzato nella variabile.

Ad esempio:

char x = 1, y = 2; 
x = x + y; // compile error: "possible loss of precision (found int, required char)" 
x = (char)(x + y); // explicit cast back to char; OK 
x += y; // compound operation-assignment; also OK 

Un modo è possibile scoprire il tipo di risultato, in generale, è quello di lanciare a un oggetto e chiedere che cosa classe che è:

System.out.println(((Object)('a' + 'b')).getClass()); 
// outputs: class java.lang.Integer 

Se sei interessato alle prestazioni, tieni presente che lo Java bytecode non ha nemmeno istruzioni dedicate per l'aritmetica con i tipi di dati più piccoli. Ad esempio, per aggiungere, ci sono le istruzioni iadd (per ints), ladd (per i long), fadd (per i float), dadd (per i doppi), e il gioco è fatto. Per simulare lo x += y con i tipi più piccoli, il compilatore utilizzerà iadd e quindi azzererà i byte superiori dell'int utilizzando un'istruzione come i2c ("int to char"). Se la CPU nativa ha istruzioni dedicate per dati a 1 o 2 byte, spetta alla macchina virtuale Java ottimizzare per quello in fase di esecuzione.

Se si desidera concatenare caratteri come stringa anziché interpretarli come un tipo numerico, esistono molti modi per farlo. Il più semplice è l'aggiunta di una stringa vuota all'espressione, poiché l'aggiunta di un char e una stringa risultano in una stringa.Tutte queste espressioni di risultato nella stringa "ab":

  • 'a' + "" + 'b'
  • "" + 'a' + 'b' (questo funziona perché "" + 'a' viene valutata prima, se il "" erano alla fine invece si otterrebbe "195")
  • new String(new char[] { 'a', 'b' })
  • new StringBuilder().append('a').append('b').toString()
  • String.format("%c%c", 'a', 'b')
+1

Risposta molto interessante e informativa, grazie! Nota, aggiungerei personalmente una sezione sull'uso del formato String (poiché si tratta di un'alternativa piacevole da leggere), ma sono davvero pignolo: P –

19

operazioni aritmetiche binari su char e byte (e short) promuovono a int - JLS 5.6.2.

+1

E operazioni aritmetiche unarie. –

2

In base allo binary promotion rules, se nessuno degli operandi è double, float o long, entrambi sono promossi a int. Tuttavia, consiglio vivamente di non considerare il tipo di carattere come numerico, che sconfigge il suo scopo.

+0

L'uso di 'char' come valore numerico è interamente all'interno del suo scopo, motivo per cui il JLS dedica tanta verbosità a tale uso. –

6

Si potrebbe voler imparare le seguenti espressioni su char.

char c='A'; 
int i=c+1; 

System.out.println("i = "+i); 

Ciò è perfettamente valido in Java e restituisce 66, il corrispondente valore del carattere (Unicode) di c+1.


String temp=""; 
temp+=c; 
System.out.println("temp = "+temp); 

Questo è troppo valida in Java e il tipo String variabile temp accetta automaticamente c di tipo char e produce temp=A sulla console.


Tutte le seguenti istruzioni sono valide anche in Java!

Integer intType=new Integer(c); 
System.out.println("intType = "+intType); 

Double doubleType=new Double(c); 
System.out.println("doubleType = "+doubleType); 

Float floatType=new Float(c); 
System.out.println("floatType = "+floatType); 

BigDecimal decimalType=new BigDecimal(c); 
System.out.println("decimalType = "+decimalType); 

Long longType=new Long(c); 
System.out.println("longType = "+longType); 

Sebbene c è un tipo di char, può essere fornito senza errori nei rispettivi costruttori e tutte le dichiarazioni di cui sopra sono trattati istruzioni come valide. Producono rispettivamente le seguenti uscite.

intType = 65 
doubleType = 65.0 
floatType = 65.0 
decimalType = 65 
longType =65 

char è un tipo integrale numerico primitivo e come tale è soggetto a tutte le regole di questi animali compresi conversioni e promozioni. Ti consigliamo di leggere su questo, e il JLS è una delle migliori fonti per questo: Conversions and Promotions. In particolare, leggere il bit breve su "5.1.2 Widening Primitive Conversion".

3

Il compilatore Java può interpretarlo come uno dei due.

controllare da scrivere un programma e alla ricerca di errori di compilazione:

public static void main(String[] args) { 
    int result1 = 'a' + 'b'; 
    char result2 = 'a' + 'b'; 
} 

Se si tratta di un carattere, quindi la prima linea mi darà un errore e il secondo no. Se è un int, allora accadrà il contrario.

L'ho compilato e ho ottenuto ..... NESSUN ERRORE. Quindi Java accetta entrambi.

Tuttavia, quando li ho stampato, ho ottenuto:

int: 195

char: Ã

Quello che succede è che quando si fa:

char result2 = 'a' + 'b' 

viene eseguita una conversione implicita (un "restringimento ristretto versione "da int a char).

+0

Sono sorpreso che non hai ricevuto un avviso del compilatore nel secondo caso sulla possibile perdita di precisione dovuta al restringimento. –

+0

@eboix: hai scritto * "il compilatore passa automaticamente a char o int" * [sic] ... Che non è corretto perché un * int * non è "castato" a un * int * e va da un * int * to a * char * non è chiamato "cast" ma "restringing primitive conversion";) – TacticalCoder

+0

Sì. Anch'io me lo aspettavo. In realtà avevo scritto parte della mia risposta prima di fare il mio programma, ma poi l'ho cancellato una volta che ho visto che non avevo avvertimenti o errori. – eboix

1

Mentre si ha già la risposta corretta (a cui si fa riferimento nella JLS), ecco un po 'di codice per verificare che si ottenga uno int quando si aggiungono due char s.

public class CharAdditionTest 
{ 
    public static void main(String args[]) 
    { 
     char a = 'a'; 
     char b = 'b'; 

     Object obj = a + b; 
     System.out.println(obj.getClass().getName()); 
    } 
} 

L'uscita è

java.lang.Integer

0

Qui c'è qualcosa di strano, però. I seguenti compila:

char x; 
x = 'a' + 'b'; 

ma questo non significa:

char x; 
x = 'a'; 
x = x + 'b'; 

Sembrerebbe che le due espressioni ('a' + 'B' e x + 'B') si traducono in numeri interi, dal seguente test:

Object obj = 'a'+'b'; 
System.out.println(obj.getClass().getName()); 

char x = 'a'; 
Object obj2 = x+'b'; 
System.out.println(obj2.getClass().getName()); 

Quindi perché il secondo caso non viene compilato? Per inciso, è possibile risolvere il problema gettando l'intera espressione come char:

x = (char)(x+'b'); 

Questo mi sembra una contraddizione nella semantica di Java - qualsiasi espressione char dovrebbe essere intercambiabili con un altro in qualsiasi contesto. Qualcuno sa di un modo per dare un senso a questo?

1

char è rappresentato come Unicode valori e dove i valori Unicode sono rappresentati da \u seguita da Hexadecimal valori.

Come ogni operazione aritmetica sul char valori promosso int, quindi il risultato di 'a' + 'b' viene calcolato come

1.) Applicare i valori Unicode su corrispondenti char utilizzando Unicode Table

2.) Applicare la conversione Hexadecimal to Decimal e quindi eseguire l'operazione sui valori Decimal.

char  Unicode  Decimal 
    a   0061   97 
    b   0062   98 + 
           195 

Unicode To Decimal Converter

Esempio

0061 

(0 * 16) + (0 * 16) + (6 * 16) + (1 * 16)

(0 * 4096) + (0 * 256) + (6 * 16) + (1 * 1)

0 + 0 + 96 + 1 = 97

0062 

(0 * 16) + (0 * 16) + (6 * 16) + (2 * 16)

(0 * 4096) + (0 * 256) + (6 * 16) + (2 * 1)

0 + 0 + 96 + 2 = 98

Quindi 97 + 98 = 195


Esempio 2

char  Unicode  Decimal 
Ջ   054b   1355 
À   00c0   192 
         -------- 
          1547 + 
          1163 - 
          7 /
         260160 * 
          11 %