2010-09-09 9 views
16

¿Puede alguien explicarme por qué el siguiente código compila OK en Java?Aritmética de enteros en Java con char y entero literal

char c = 'a' + 10; 

¿Por qué esto no es equivalente al siguiente, que no se compila?

int i = 10; 
char c = 'a' + i; 

La Especificación del Lenguaje Java (sección 3.10.1) afirma que "un literal entero es de tipo long si se añade como sufijo con una letra ASCII L o L (ELL), de lo contrario es de tipo int (§4.2 .1). " La Sección 4.2.2 se refiere a "Los operadores numéricos, que dan como resultado un valor de tipo int o long". Entonces, el resultado de la adición debe, en mi entender, ser un int, que no se puede asignar a la variable charc.

Sin embargo, compila bien (al menos en Sun JDK 1.6.0 versión 17 y en Eclipse Helios).

Más bien un ejemplo artificial tal vez, pero se usa en un curso introductorio de Java que he estado enseñando, y ahora se me ocurre que realmente no entiendo por qué funciona.

+3

Gracias a todos los que respondieron. Para cualquier persona interesada, la sección 5.2 de la especificación de idioma (Conversión de asignación) dice "Además, si la expresión es una expresión constante (§15.28) de tipo byte, short, char o int: ... Una conversión primitiva de estrechamiento puede usarse si el tipo de la variable es byte, short o char, y el valor de la expresión constante es representable en el tipo de la variable ". – Ben

+1

Si usted, como yo, tropieza con esto porque quiere saber cómo convertir realmente un carácter indexado en una cadena, aquí va; cuando 'i = 2' luego' String.valueOf ((char) ('a' + i)) 'devuelve la cadena" c ". – JohnnyLambada

Respuesta

9

'a' + 10 es una expresión de la constante de tiempo de compilación con el valor de 'k', que puede inicializar una variable de tipo char. Esto es lo mismo que poder asignar una variable byte con un entero literal en [-128, 127]. Un byte en el rango de [128, 255] puede ser más molesto.

+0

Gracias. Buscar * expresión constante en tiempo de compilación * me llevó a la sección correspondiente de la especificación del lenguaje. – Ben

13

Es porque el compilador puede comprobar que ('a' + 10) está dentro de los límites de un char mientras que no puede (en general) comprobar que 'a' + <an integer> está dentro de los límites.

+0

char c = 65535; compila, pero no char c = 65536; – einarmagnus

+0

char tiene dos bytes, por lo que tiene sentido. – einarmagnus

+0

'char c = 103000;' no. UCS-2 ftw! –

1

La constante es de un tipo diferente (sé que la especificación dice que 10 debe ser un int, pero el compilador no lo ve de esa manera).

En char c = 'a' + 10, 10 en realidad se considera una variable constante de tipo char (por lo que se puede agregar a a). Por lo tanto, char c = char + char funciona.

En int i = 10; char c = 'a' + i; va a añadir un char a un número entero (un entero puede ser mucho más grande que un char, por lo que elige el más grande de tipo de datos [int] que es el resultado a.k.a: 'a' + i = int + int). Por lo tanto, el resultado de la adición es un número entero, que no puede caber en el char c.

Si Casted explícitamente i ser un char (ej .: char c = 'a' + (char)i;) que podría funcionar o si se hizo lo contrario (ej .: int c = (int)'a' + i;) que iba a funcionar.

+0

No creo que sea del todo correcto decir que 10 se considera de tipo char. Por el contrario, como dice Tom Hawtin, la expresión '' a '+ 10' es una * constante de tiempo de compilación * y, por lo tanto, el compilador puede hacer una conversión de estrechamiento. En realidad, 'char c = 'a' + (char) i;' no funciona porque el lado derecho es de tipo 'int' y no es una constante en tiempo de compilación. – Ben

3

char es en realidad un entero de 16 bits sin signo con un rango de 0-65535. Por lo tanto, puede asignar cualquier literal entero en ese rango a un char, por ejemplo, "char c = 96", que da como resultado "c" manteniendo el carácter "a". Puede imprimir el resultado usando System.out.println (c).

Para la expresión constante en el lado derecho de "char c = 'a' + 10", 'a' se promueve primero a int debido a las reglas de promoción numérica de Java y el valor entero es 96. Después añadiéndole 10, obtenemos un entero literal 106, que se puede asignar a un carácter.

El lado derecho de "char c = 'a' + i" no es una expresión constante y la regla de asignación de resultado de expresión requiere un molde explícito de int a char, es decir, "char c = (char) ('a' + i) ".

Cuestiones relacionadas