Documentos de Académico
Documentos de Profesional
Documentos de Cultura
4. Conversión y Casting
Este capítulo discute las formas en que un valor dato puede cambiar su
tipo. Los valores pueden cambiar un tipo a otro explícita o
implícitamente ; esto es, cualquier tipo al que cambie, ya sea por
petición suya o iniciativa del sistema. Java brinda mucha importancia al
tipo, y una programación exitosa en Java requiere que usted sea
cuidadoso con los cambios de tipo.
Por supuesto, el sexto elemento del vector debe ser capaz de ser
tratado como un botón. Hay reglas de tiempo de compilación y tiempo
de corrida que deben ser observadas. Este capítulo lo familiarizará con
tales reglas.
myVector.addElement( myColor );
Las buenas noticias son que la mayoría de las reglas van de acuerdo con
el sentido común, y la mayoría de las combinaciones pueden ser
generalizadas en reglas generalizadas. Hacia el final de éste capítulo,
usted sabrá cuándo puede efectuar cast explícito, y cuándo el sistema
implícitamente hará la conversión por usted.
Primitivas y Conversión
Las dos principales categorías de los tipos de datos Java son primitivas y
obejetos.
Conversión de primitivas.
casting de primitivas.
conversión de referencias a objetos.
casting de referencias a objetos.
asignación.
Llamada de métodos.
Promoción aritmética.
1. int i;
2. double d;
3. i = 10;
4. d = i; // asigna un valor de tipo entero a una variable double.
1. double d;
2. short s;
3. d = 1.2345;
4. s = d; // asigna un valor double a una variable short
Figura 4.1
Conversión de agrandamiento
x x x x x ...
0 ... 0 x x x x x ...
Las conversions de agrandamiento no pierden información acerca de la
magnitud de un valor. En el primer ejemplo de ésta sección, un valor
entero fue asignado a una variable double. Esto fue lícito, porque los
valores double son por así decirlo más amplios que los enteros, Las
conversiones de ampliamiento en Java son:
Figura 4.2
Conversiones de ampliamiento
char
int long float double
byte short
De un byte a un char.
De un short a un byte o a char.
De un char a un byte o a short.
De un int a un byte, a short, o a char.
De un long a un byte, a short, a char, o a int.
De un float a un byte, a short, a char, a int, o a long.
De un double a un byte, a short, a char, a int, a long, o a float.
1. float frads;
2. double d;
3. frads = 2.34567f;
4. d = Math.cos( frads ); // pasa un flotante a un método que espera un double
1. short s = 9;
2. int i = 10;
3. float f = 11.1f;
4. double d = 12.2;
5. if ( ++s*I >= f/d )
6. System, out. println( '>>>>" );
7. else
8. System, out. println( "<<<<" );
Figura 4.3
Operadores + - ++ -- ~
unarios
Operadores + - * / % >> >>> <<
binarios
& ^ |
Primitivas y Casting
1. int i = 5;
2. double d = (double)i;
1. int i = 5;
2. double d = i;
Los Casts son requeridos cuando usted desea realizar una conversión de
estrechamiento, como la conversión no será nunca hecha
implícitamente, usted tiene que programar un cast explícito que
convenza al compilador de que usted realmente quiere esa conversión
de reducción.
1. short s = 259;
2. byte b = s: // error de compilación
3. System.out. println( s = " + s + ", b = " + b );
1. short s = 259;
2. byte b = (byte)s; // explicit cast
3. System.out.println( b = " + b );
b=3
Figura 4.4
0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1
b = (byte)s
0 0 0 0 0 0 1 1
1. int i = 2;
2. double radians;
.
.
//cientos de líneas de código después.
600. radians = (double)i;
Figura 4.6
NewType es OldType debe ser NewType debe ser NewType debe ser
una clase subclase de Object Object
NewType
NewType es una OldType debe Oldtype debe ser NewType debe ser
interfaz implementar la sub-interfaz de Cloneable
interfaz NewType NewType
Recordar que con primitivas, las conversiones eran permitidas, dado que
eran de ampliación “widening”. La noción de ampliación no se aplica
realmente a referencias, pero hay un principio similar. En general, la
conversión de referencias a objetos es permitida cuando la dirección de
la conversión es hacia arriba en la jerarquía de herencia, que es, el viejo
tipo debe heredar del nuevo tipo. Ésta regla general no cubre los 9
casos pero es útil.
Object
Fruit
1
Recuerde: Esto no significa que usted no pueda hacerlo por casting.
1. Grapefruit g = new Grapefruit();
2. Squeezable squee = g; // no hay problema
3. Grapefruit g2 = squee; // error
La tercera línea es una error, porque una interfaz nunca puede ser
implícitamente convertida a cualquier tipo referencia más que el objeto.
1. Fruit fruits[];
2. Lemon lemons[];
3. Citrus citruses[] = new Citrus[ 10 ];
4. for ( int i = 0; i < 10; i++ ) {
5. citruses[ i ] = new Citrus();
6. }
7. fruits = citruses; // no hay problema
8. lemons = citruses; // error
Para ver cómo las reglas tienen sentido en el contexto de llamadas del
método, considere la sumamente útil clase Vector. Puede guardar
cualquier tipo de dato en un Vector (algo no-primitivo, eso es) llamando
el método addElement (obj del Objeto). Por ejemplo, el código
siguiente almacena a Tangelo en un vector:
Figura 4.7
Referencias
b
1 0 1 0 . . . 0 1 Blob b = new Blob();
b es una referencia:
un valor de 32-bit
contiene la dirección
del objeto Blob
Objeto de tipo Blob en
RAM
Serializable ser;
1 0 1 0 . . . 0 1
Object obj;
1 0 1 0 . . . 0 1
Vector vec;
1 0 1 0 . . . 0 1
Stack stk;
1 0 1 0 . . . 0 1
No hay ningún escape el hecho que hay varias reglas que gobiernan el
casting para objetos. Las buenas noticias son que la mayoría de las
reglas cubre casos oscuros. Podría empezar viendo el cuadro de
conversión por casting con toda sus complicadas relaciones, pero
después de esto tendrá unas ideas simples que serán evidentes en la
mayoría de las situaciones comunes.
Figura 4.9
Reglas en tiempo de Compilación
para casting en referencia a objetos
1. NewType nt;
2. OldType t:
3. nt = (NewType)ot;
NewType es una Siempre bien OldType debe Casi siempre NewType debe
interface implementar la bien ser Cloneable
interfaz
NewType
NewType es un OldType debe Error de Error de OldType debe
array ser compilación compilación ser un array del
Object mismo tipo de
referencia que
puede ser
convertido a
cualquier tipo
del arreglo
NewType .
Mire una vez más la jerarquía de Fruit/Citrus que vio antes en este
capítulo. Primero, considere el código siguiente:
Este código tiene cuatro referencias pero sólo un objeto. La clase del
objeto es Grapefruit, porque el constructor de Grapefruit que se llama
en línea 4. La asignación c = g en la línea 5 es una conversión de la
asignación absolutamente legal ("sobre" la jerarquía de herencia), así
que ningún cast explícito se requiere. En las líneas 6 y 7, el Citrus hace
cast a Grapefruit y a Tangelo. Para el llamado a casting entre los tipos
de la clase, uno de las dos clases (no importa cuál) debe ser una
subclase de la otra.
5. gl = (Grapefruit)s;
1. Grapefruit g[];
2. Squeezable s[];
3. Citrus c[];
4. g = new Grapefruit[ 500 ];
5. s = g; // convierte el array Grapefruit en array Squeezable
6. c = (Citrus[])s; // hace cast de array Squeezable a array Citrus
Los valores primitivos y referencias del objeto son tipos muy diferentes
de datos. Los dos pueden convertirse (implícitamente) o hacer cast
(explícitamente). Los cambios del tipo Primitivos se producen por:
Conversión de Asignación
Conversión por le Método Call
Casting Explícito
Autoevaluación:
1. byte b = 5;
2. char c = 5;
3. short s = 55;
4. int i = 555;
5. float f = 555.5f;
6. b = s;
7. i = c;
8. if ( f > b )
9. f = i;
1. byte b1 = 2;
2. byte b2 = 3;
3. b = b1*b2;
1. byte b = 11;
2. short s = 13;
3. result = b * ++s;
1. class Cruncher {
2. void crunch( int i ) { System.out.println( "int version" ); }
3. void crunch( String s ) { System.out.println( "String version" ); }
4. public static void main( String[] args ) {
5. Cruncher crun = new Cruncher();
6. char ch = 'p';
7. crun.crunch( ch );
8. }
9. }
Animal
Mammal
A. La línea 5 no compila.
B. La línea 6 no compila.
C. El código compila pero se produce un error de Excepción en la línea
6.
D. El código compila y corre.
E. El código compila y corre, pero el cast en la línea seis no es requerido
y puede ser eliminado.
1. Raccoon rocky;
2. SwampThing pogo;
3. Washer w;
4.
5. rocky = new RaccoonQ;
6. w = rocky;
7. pogo = w;