Professional Documents
Culture Documents
4. Conversin y Casting
Este captulo cubre el siguiente objetivo del examen de certificacin en
Java
Determinar el efecto en los objetos y valores primitivos de pasar
variables a mtodos y realizar asignaciones u otras operaciones de
asignacin en se mtodo.
Cada variable de Java tiene un tipo. Los tipos de datos primitivos
incluyen int, long, double, y as sucesivamente. Los tipos de datos de
referencia a objetos pueden ser clases (tales como Vector o Graphics)
o interfaces (como lo es LayoutManager o Runnable). Pueden ser
tambin arreglos de primitivas, objetos o arreglos.
Este captulo discute las formas en que un valor dato puede cambiar su
tipo. Los valores pueden cambiar un tipo a otro explcita o
implcitamente ; esto es, cualquier tipo al que cambie, ya sea por
peticin suya o iniciativa del sistema. Java brinda mucha importancia al
tipo, y una programacin exitosa en Java requiere que usted sea
cuidadoso con los cambios de tipo.
Cambios de tipo Implcitos o explcitos
Usted puede explcitamente cambiar el tipo de un valor por casting. Para
hacer casting de una expresin a un nuevo tipo, slo ponga como prefijo
de la expresin el nuevo tipo en parntesis. Por ejemplo, la siguiente
lnea de cdigo trae un elemento de un vector, realiza cast de ese
elemento al tipo Button, y asigna el resultado a una variable llamada
btn:
Button btn = (Button)myVector.elementAt( 5 );
Por supuesto, el sexto elemento del vector debe ser capaz de ser
tratado como un botn. Hay reglas de tiempo de compilacin y tiempo
de corrida que deben ser observadas. Este captulo lo familiarizar con
tales reglas.
Hay situaciones en las cuales el sistema implcitamente cambia el tipo
de una expresin sin que usted explcitamente elabore el cast. Por
ejemplo, suponga que usted tiene una variable llamada myCol que es
una instancia de Color, y usted quiere almacenar myCol en un vector.
Usted debera probablemente hacer lo siguiente:
myVector.addElement( myColor );
Hay ms en ste cdigo de lo que se ve a simple vista.
El mtodo addElement() de la clase Vector es declarada con un
parmetro de tipo Object, no del tipo Color. Como el argumento es
pasado al mtodo, el sistema entiende un cambio de tipo implcito. El
cambio de tipo no explcito es conocido como conversin.
La conversin como el casting, es gobernado por un nmero de reglas.
A diferencia de las reglas de casting, todas las reglas de conversin son
forzadas en tiempo de compilacin.
El nmero de reglas de casting y conversin es bastante largo, debido al
gran nmero de casos que son considerados. (Por ejemplo, se puede
hacer cast de char a double?, se puede convertir una interfaz a una
clase final?).
Las buenas noticias son que la mayora de las reglas van de acuerdo con
el sentido comn, y la mayora de las combinaciones pueden ser
generalizadas en reglas generalizadas. Hacia el final de ste captulo,
usted sabr cundo puede efectuar cast explcito, y cundo el sistema
implcitamente har la conversin por usted.
Primitivas y Conversin
Las dos principales categoras de los tipos de datos Java son primitivas y
obejetos.
Los tipos de datos primitivos son int, float, Boolean, y as
sucesivamente. (Hay 8 tipos de datos primitivos en total; vea el captulo
1 para una explicacin completa de las primitivas de Java).
Los tipos de dato Object (o ms apropiadamente, tipos de dato de
referencia a objetos) son todos los cientos de clases e interfaces del
JDK, ms la infinitud de clases e interfaces desarrolladas por los
programadores de Java.
Tanto a los valores primitivos como referencias a objetos se les puede
Conversin de primitivas.
casting de primitivas.
conversin de referencias a objetos.
casting de referencias a objetos.
asignacin.
Llamada de mtodos.
Promocin aritmtica.
int i;
double d;
i = 10;
d = i;
// asigna un valor de tipo entero a una variable double.
double d;
short s;
d = 1.2345;
s = d; // asigna un valor double a una variable short
0
...
0 x x x x x ...
Las conversions de agrandamiento no pierden informacin acerca de la
magnitud de un valor. En el primer ejemplo de sta seccin, un valor
entero fue asignado a una variable double. Esto fue lcito, porque los
valores double son por as decirlo ms amplios que los enteros, Las
conversiones de ampliamiento en Java son:
De
De
De
De
De
De
un
un
un
un
un
un
char
int
byte
long
float
double
short
De
De
De
De
De
De
De
un
un
un
un
un
un
un
byte a un char.
short a un byte o a char.
char a un byte o a short.
int a un byte, a short, o a char.
long a un byte, a short, a char, o a int.
float a un byte, a short, a char, a int, o a long.
double a un byte, a short, a char, a int, a long, o a float.
float frads;
double d;
frads = 2.34567f;
d = Math.cos( frads ); // pasa un flotante a un mtodo que espera un double
double d = 12.0;
Object ob = myVector.elementAt( d );
El error de compilador dice "Incompatible type for method. Explicit cast
needed to convert double to int.".
sto significa que el compilador no puede convertir el argumento de tipo
double al tipo que es soportado por la versin del mtodo elementAt().
El entiende que la nica versin de elementAt() es la versin que toma
como argumento a un entero. Entonces un valor puede ser nicamente
pasado a elementAt() si ese valor es un int o puede ser convertido a int.
Afortunadamente, la regla que gobierna qu conversiones por llamado
de mtodos son permitidas, es la misma regla que gobierna las
conversiones de asignacin. Conversiones de ampliamiento (como las
mostradas en la figura 4.2) son permitidas; las conversiones de
estrechamiento son prohibidas.
La ltima clase de conversin de primitivas a considerar es la promocin
aritmtica, que suceden con sentencias aritmticas. Mientras el
compilador est tratando de percibir muchas diferentes clases de
operando.
Considere el siguiente fragmento:
1.
2.
3.
4.
5.
6.
7.
8.
short s = 9;
int i = 10;
float f = 11.1f;
double d = 12.2;
if ( ++s*I >= f/d )
System, out. println( '>>>>" );
else
System, out. println( "<<<<" );
++
--
&
*
^
/
|
~
%
>>
>>>
<<
int i = 5;
double d = (double)i;
int i = 5;
double d = i;
Los Casts son requeridos cuando usted desea realizar una conversin de
estrechamiento, como la conversin no ser nunca hecha
implcitamente, usted tiene que programar un cast explcito que
convenza al compilador de que usted realmente quiere esa conversin
de reduccin.
La reduccin corre el riesgo de prdida de informacin; el cast le dice al
compilador que usted acepta el riesgo. Por ejemplo, el siguiente cdigo
genera un error de compilacin:
1.
2.
short s = 259;
byte b = s:
// error de compilacin
3.
short s = 259;
byte b = (byte)s;
// explicit cast
System.out.println( b = " + b );
b = (byte)s
int i = 2;
double radians;
.
.
//cientos de lneas de cdigo despus.
600.
radians = (double)i;
El cast en la ltima lnea no es requerido, pero el sirve como un buen
recordatorio para los lectores (incluido usted mismo) que pueden haber
olvidado el tipo de radianes. Hay dos simples reglas que gobiernan el
casting de tipos primitivos:
OldType es una
interfaz
OldType es un
arreglo
NewType es
una clase
NewType es una
interfaz
OldType debe
implementar la
interfaz NewType
NewType is un
arreglo
Error de
compilacin
Error compilacin
Figura 4.6
La jerarqua frutal
Object
Fruit
Lemon
Citrus
(implementa Squeezable)
Tangelo
Grapefruit
1.
2.
3.
Fruit fruits[];
Lemon lemons[];
Citrus citruses[] = new Citrus[ 10 ];
for ( int i = 0; i < 10; i++ ) {
citruses[ i ] = new Citrus();
}
fruits = citruses;
// no hay problema
lemons = citruses;
// error
Para ver cmo las reglas tienen sentido en el contexto de llamadas del
mtodo, considere la sumamente til clase Vector.
Puede guardar
cualquier tipo de dato en un Vector (algo no-primitivo, eso es) llamando
el mtodo addElement
(obj del Objeto). Por ejemplo, el cdigo
siguiente almacena a Tangelo en un vector:
1.
2.
3.
1.
2.
255 );
b
1
Serializable ser;
1
Object obj;
1
Vector vec;
1
Stack stk;
1
casting para objetos. Las buenas noticias son que la mayora de las
reglas cubre casos oscuros. Podra empezar viendo el cuadro de
conversin por casting con toda sus complicadas relaciones, pero
despus de esto tendr unas ideas simples que sern evidentes en la
mayora de las situaciones comunes.
Para el casting de referencia a objeto, no hat tres pero si cuatro
posibilidades para el tipo viejo y el nuevo tipo. Cada tipo puede ser una
clase no-final, una clase final, una interface, o un array. La primera
regla fortalece lo que pasa en tiempo de compilacin. Las reglas en
tiempo de compilacin se resumen en la Figura 4.9.
Figura 4.9
Reglas en tiempo de Compilacin
para casting en referencia a objetos
1.
2.
3.
NewType nt;
OldType t:
nt = (NewType)ot;
OldType debe
extender
NewType, o
viceversa
OldType debe
extender
NewType
Siempre Bien
NewType debe
ser Object
OldType y
NewType debe Error de
NewType deben implementar la Compilacin
ser la misma
interfaz oldtype
clase
OldType debe
implementar la
interfaz
NewType
Casi siempre
bien
NewType debe
ser Cloneable
Error de
compilacin
Error de
compilacin
OldType debe
ser un array del
mismo tipo de
referencia que
puede ser
convertido a
cualquier tipo
del arreglo
NewType .
// la clase es Grapefruit
//Asignacin legal de conversin, no
// necesita cast
// cast vlido
// cast no vlido (throws an exception)
Este cdigo tiene cuatro referencias pero slo un objeto. La clase del
objeto es Grapefruit, porque el constructor de Grapefruit que se llama
en lnea 4. La asignacin c = g en la lnea 5 es una conversin de la
asignacin absolutamente legal ("sobre" la jerarqua de herencia), as
que ningn cast explcito se requiere. En las lneas 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 cul) debe ser una
subclase de la otra.
El primer cast es Citrus a la subclase Grapefruit; el segundo es de Citrus
a la subclase Tangelo. As ambos cast son legales en tiempo de
compilacin. El compilador no puede determinar la clase referenciada
por el objeto c as que acepta cast y permite determinar el resultado en
runtime.
Cuando el cdigo se ejecuta, la Mquina Virtual Java intenta ejecutar
lnea 6: G2 = (Grapefruit)c; La clase de c se determina para ser
Grapefruit, y no hay ninguna objecin a convertir Grapefruit a
Grapefruit.
La lnea 7 obliga (al runtime) cast de c para el tipo Tangelo. La clase de
c todava es Grapefruit, y un Grapefruit no puede hacer cast a un
Tangelo. Para que el cast sea legal, la clase c tendra que ser Tangelo o
alguna subclase de Tangelo. Si ste no es el caso, una excepcin del
runtime (java.lang.ClassCastException) se lanza.
Ahora tome un ejemplo donde un objeto hace cast a un tipo interface.
Considere el fragmento del cdigo siguiente:
1.
2.
3.
4.
5.
gl = (Grapefruit)s;
Grapefruit g[];
Squeezable s[];
Citrus c[];
g = new Grapefruit[ 500 ];
s = g;
// convierte el array Grapefruit en array Squeezable
c = (Citrus[])s; // hace cast de array Squeezable a array Citrus
Conversin de Asignacin
Conversin por le Mtodo Call
Casting Explcito
Autoevaluacin:
1. Cual de las siguientes declaraciones es correcta? (Escoja ms de
una)
A. Solamente las primitivas son convertidas automticamente; para
cambiar el tipo de referencia a un objeto se debe hacer cast.
B. Solamente las referencias a objetos son convertidas
automticamente; para cambiar el tipo de una primitiva, se debe
hacer cast.
C. La promocin Aritmetica de referencia a objetos requiere casting
explicito.
byte b = 5;
char c = 5;
short s = 55;
int i = 555;
float f = 555.5f;
b = s;
i = c;
if ( f > b )
f = i;
byte b1 = 2;
byte b2 = 3;
b = b1*b2;
A.
B.
C.
D.
E.
byte b = 11;
short s = 13;
result = b * ++s;
class Cruncher {
void crunch( int i )
{ System.out.println( "int version" ); }
void crunch( String s ) { System.out.println( "String version" ); }
4.
5.
6.
7.
8.
9.
6.
7.
8.
ob = strArr[ 5 ];
floater = ob;
ob = floater;
Mammal
Dog
Cat
(implements Washer)
1.
2.
3.
4.
5.
6.
Raccoon
SwampThing
(implements Washer)
1.
2.
3.
4.
5.
6.
7.
Cat sunflower;
Washer wawa;
SwampThing pogo;
sunflower = new Cat();
wawa = sunflower;
pogo = (SwampThing)wawa;
Raccoon rocky;
SwampThing pogo;
Washer w;
rocky = new RaccoonQ;
w = rocky;
pogo = w;