Asignaciones, Widening y Cast.
La operación de asignación nos sirve para dar valor a una variable.
La forma genérica de una asignación es la siguiente:
variable = valor;
Donde valor puede ser un literal, otra variable o una expresión.
El proceso de la asignación se realiza en dos fases. En primer lugar, se evalúa la parte derecha y se obtiene un valor. En segundo lugar, se asigna ese valor a la variable de la parte izquierda.
Literales
Ya comentamos que tenemos ocho tipos primitivos en Java: byte, short, int, long, float, double, char y boolean. Un literal es un valor concreto de un tipo.
Enteros
Se pueden representar utilizando una notación decimal, octal o hexadecimal.
15 formato decimal.
017 formato octal, el prefijo 0 indica un valor octal.
0xF formato hexadecimal, el prefijo 0x indica un valor hexadecimal.
Un literal entero se considera por defecto de tipo int. Para indicar que queremos que sea de tipo long debemos acompañarlo de ‘l’ o ‘L’. Algunos literales enteros: 15, 320, 29999, 130000, 250L.
Reales
Un literal real se considera por defecto de tipo double. Para indicar que queremos que sea de tipo float debemos acompañarlo de ‘f’ o ‘F’. Algunos literales reales en coma flotante: 3.4, 1293.239, 150.23F.
Carácter
Un literal char se escribe entre comillas simples. Como son carácteres Unicode también se puede especificar el carácter en concreto por sus dígitos hexadecimales.
Algunos literales char: ‘b’, ‘z’, ‘\n’, ‘\t’, ‘\u003B’
Lógico
Los literales son false y true.
Expresiones
Es frecuente que nos encontremos expresiones en la que participan diferentes tipos de datos. Algunos tipos de datos pueden ser compatibles (enteros con caracteres p.e), mientras que otros no (enteros con reales).
Los booleanos no son compatibles con ningún otro tipo de dato.
En las expresiones con datos enteros el resultado será al menos un int o el tipo del mayor operando de la expresión.
byte a = 10; byte b = 20; byte c = (a + b) * 0.5; //El resultado de (a+b) * 0.5 es de tipo double.
En este caso el compilador generará un error, se necesita una conversión.
En Java las conversiones pueden ser implícitas o explícitas.
Conversión Implícita (Widening)
Se produce cuando los tipos son compatibles y Java realiza la conversión de forma automática.
Siempre es posible asignar un valor de un tipo más pequeño en una variable de un tipo mayor.
Grande = Pequeño; //OK
1 |
long a = 100 ; //100 al ser un literal entero, es de tipo int. |
No hay problema en guardar este valor en una variable long. La conversión es automática.
Conversión Explícita (Cast)
Cuando los tipos son incompatibles o existe la posibilidad de perder información en una asignación, el compilador dará un error pidiendo que se confirme esa asignación con una conversión explícita.
Pequeño = Grande; //ERROR
1 |
int a = 100L; //ERROR 100L es un literal de tipo long y se quiere asignar a una variable int. |
2 |
int a = ( int ) 100L; // OK |
El compilador generará error. Como sabemos que en la asignación no hay peligro de perder información al caber 100 perfectamente en un int, convertimos explícitamente.
Casos Posibles de Asignaciones
- Asignación de Iguales: Se produce cuando el tipo del valor a asignar coincide con el tipo de la variable. En esta situación no hay ningún problema.
1
char
c =
'a'
;
2
int
entero =
100
;
3
int
suma = entero +
25
;
4
double
precio =
950.283
;
5
boolean
indCerrado =
false
;
- Conversión de ampliación (Widening): Ocurre cuando el tipo del valor a asignar es más pequeño que el tipo de la variable.
1
//grande = pequeño; //OK
2
int
a =
150
;
//Declaramos un entero
3
long
var = a;
//La variable a se puede asignar al long var, ya que vamos de pequeño a grande.
4
double
b =
15
.3f * var;
- Conversión de reducción (Narrowing): Ocurre cuando el tipo del valor a asignar es más grande que el tipo de la variable. Es necesaria la conversión explícita.
01
//pequeño = grande; //ERROR
02
//pequeño = (pequeño) grande; //OK
03
long
grande = 5500L;
04
int
pequeño = (
int
) grande;
//Es necesario hacer un casting a int.
05
byte
primero =
5
;
06
byte
segundo =
20
;
07
byte
suma = (
byte
) (primero + segundo);
//La suma de dos bytes es un int, por lo tanto necesita
08
//un casting a byte
- Excepción:
Cuando el valor a asignar es una expresión constante de tipo byte, short, char o int el compilador hace la conversión automáticamente. Esto se llama compile-time narrowing of constants:1
byte
auto =
10
;
//OK, no hace falta hacer byte auto = (byte) 10;
Si la variable a asignar es final y “cabe” en el destino no es necesario casting:1
final
short
prueba =
100
;
2
byte
destino = prueba;
//OK
4
final
short
prueba =
300
;
//sobrepasa el valor posible para los byte.
5
byte
destino = prueba;
//ERROR: possible loss of precision
- Nota:
Aunque tengamos un valor real que pueda caber en un “float” y lo queremos asignar a un double, siempre será necesario el sufijo o el casting:1
double
f =
500.7
;
//ERROR
2
double
f =
500
.7f;
//OK
3
double
f = (
float
)
500.7
;
//OK
- Excepción:
- Conversión de Tipos de Referencia:
Se puede asignar a un tipo menos especializado un tipo más especializado en la jerarquía.Padre = Hijo //OK
1
Persona pe =
new
Programador();
Esto es posible porque un objeto hijo (más especializado) puede hacer todo lo que haga el padre (menos especializado) pero no al revés.Hijo = Padre //ERROR
En estas asignaciones es necesario ningún tipo de conversión.
Cualquier expresión entera siempre se podrá asignar a una variable double, ya que es el mayor tipo entero.
1 |
Programador pro = new Persona(); //ERROR |
Ejemplo de código
package sobreescritura;
public class Pruebas {
public static void main (String args[]){
double a = 0;
System.out.println(a);
a = 0.0; //DOUBLE ACEPTA ASIGNACIONES DECIMALES SIN NECESIDADES DE ESPECIFICARLAS
System.out.println(a);
a = 0.0f; //DOUBLE ACEPTA ASIGNACIONES DE TIPO FLOAT
System.out.println(a);
a = 0.0d;
System.out.println(a);
float b = 0;
System.out.println(a);
//b = 0.0; FLOAT NO ADMITE ASIGNACIONES CON DECIMALES SIN INDICARLO DE MANERA EXPLÍCITA
System.out.println(a);
b = 0.0f;
System.out.println(a);
//b = 0.0d; FLOAT NO ADMITE ASIGNACIONES DE TIPO DOUBLE
System.out.println(a);
//b = a; FLOAT NO PUEDE TENER ASIGNACIONES DE TIPO DOUBLE
a = b; //SIN EMBARGO, DOUBLE, PUEDE TENER ASIGNACIONES DE TIPO FLOAT
}
}
Reader Comments (2)
Muy buen artículo. Buenos ejemplos y se entienden los conceptos.
Gracias
De nada, ajaristi, un placer! Asi aprendemos todos.