You are on page 1of 29

Capitulo 4

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

efectuar procedimientos de casting y conversin, hay 4 casos a


considerar:

Conversin de primitivas.
casting de primitivas.
conversin de referencias a objetos.
casting de referencias a objetos.

El tpico ms sencillo es la conversin implcita de primitivas (que son:


int, long, char,, y as sucesivamente). Todas las conversiones de tipos
de datos primitivos toman lugar en tiempo de compilacin; esto es
porque toda la informacin necesaria para determinar si la conversin es
legal o no en tiempo de compilar. (Este no es el caso de los datos
Object, que ver usted ms adelante en ste captulo).
Hay 3 contextos de situaciones en que la conversin de una primitiva
puede ocurrir:

asignacin.
Llamada de mtodos.
Promocin aritmtica.

Las siguientes secciones tartan con los contextos en turno.


Conversin de primitivas: Asignacin
La conversin por asignacin sucede cuando usted asigna un valor a una
variable de un tipo diferente al valor original, por ejemplo:
1.
2.
3.
4.

int i;
double d;
i = 10;
d = i;
// asigna un valor de tipo entero a una variable double.

Obviamente, d no puede retener un valor entero. Al momento que la


cuarta lnea de cdigo es ejecutada, el entero 10 que es almacenado en
la variable i se convierte al valor de doble precisin 10.00000000000
(los ceros restantes se omiten por brevedad).

El cdigo anterior es perfectamente lcito. Algunas asignaciones, a la


otra mano, son ilegales. Por ejemplo, el siguiente cdigo no compilar:
1.
2.
3.
4.

double d;
short s;
d = 1.2345;
s = d; // asigna un valor double a una variable short

Este cdigo no compilar. (El mensaje de error dice "Incompatible


type for =."). El compilador reconoce que est tratando de introducir
un valor de tipo double en una variable short, lo cual es como derremar
un cuerto de caf en un una taza de caf de 8 onzas. Puede hacerse
(sto es, la asignacin de valor puede hacerse; la cuestin del caf es
imposible), pero usted debe hacer uso de un cast explcito, que ser
explicado en la siguiente seccin.
Las reglas generales para conversin por asignacin pueden resumirse
as:

Un booleano no puede ser convertido a otro tipo de datos.

Un no booleano puede ser convertido a otro no tipo booleano si la


conversin es a un tipo ms grande.

Un no booleano no puede ser convertido en otro tipo no booleano,


si la conversin debera ser a un tipo ms pequeo.

Conversiones a tipos ms grandes cambian un valor a un tipo que se


acomoda a un mayor rango de valores a los que el valor original poda
acomodarse. En la mayora de los casos, el nuevo tipo tiene ms bits
que el original y puede ser visualizado como ms amplio que el original,
como se muestra en la figura 4.1
Figura 4.1
Conversin de agrandamiento
x x x x x ...

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

byte a un short, a un int, a un long, un float o double.


short a un int, a un long, a un float o double.
char a un int, a un long, a un float, o double.
int a un long, a un float, o double.
long a un float o double.
float a un double.

La figura 4.2 ilustra todas las conversiones de ampliamiento. Las flechas


pueden ser tomadas como puede ser convertido a. Para determinar si
es legal convertir un tipo a otro, encuentre el primer tipo en la figura y
vea si usted puede alcanzar el segundo tipo siguiendo las flechas.
Figura 4.2
Conversiones de ampliamiento

char
int
byte

long

float

double

short

La figura muestra, por ejemplo, que es perfectamente legal para asignar


un valor byte a una variable flota, porque usted puede trazar un camino
de byte a flota siguiendo las flechas (byte a short a entero a long o
float). Usted no puede al contrario, trazar un camino de long a short, as
entonces no es legal asinar un valor long a una variable short.
La figura 4.2 es fcil de memorizar. La figura consiste en mayora de los
tipos numricos en orden de tamao. La nica pieza extra de
informacin es char, excepto que vaya en el nico lugar en que puede
ir: un char de 16 bits cabe en un entero de 32 bits. (ntese que usted
no puede convertir un byte a char o char a short, an cuando se ve
razonable de hacer).

Cualquier conversin entre tipos primitivos que no es representada por


un camino de las flechas de la figura 4.2 es un conversin de
estrechamiento narrowing. stas conversiones pierden informacin
acerca de la magnitud del valor que est siendo convertido, y no son
permitidas como asignaciones . Es geomtricamente imposible retratar
las conversiones de estrechamiento en un grfico como la figura 4.2.
pero ellas pueden ser resumidas as:

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.

Usted no necesita memorizar sta lista. Simplemente representa todas


las conversiones no mostradas en la figura 4.2, que ms fcil de
memorizar.
Conversin de primitivas: Llamado de mtodos
Otra clase de conversin es el la conversin por llamado de mtodos
que sucede cuando usted pasa un valor de un tipo como un argumento
de un mtodo que espera un tipo diferente. Por ejemplo, el mtodo
cos() de la clase Math, espera un argumento sencillo de un tipo double.
Considere el siguiente cdigo:
1.
2.
3.
4.

float frads;
double d;
frads = 2.34567f;
d = Math.cos( frads ); // pasa un flotante a un mtodo que espera un double

El valor float en frads es automticamente convertido a un valor double


antes de ser manipulado por el mtodo cos(). Tal como en las
conversiones de asignacin, hay reglas estrictas que gobiernan que son
permitidas y que conversiones pueden ser rechazadas por el compilador.
El cdigo a continuacin totalmente razonable genera un error de
compilacin (asumiendo que hay un vector llamado myVector).

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( "<<<<" );

El cdigo en la lnea 5 multiplica un short incrementado por un int;


entonces el divide un flota por un double; finalmente el compara los dos
resultados. Atrs de las escenas, el sistema est haciendo una extensiva
conversin de tipo para asegurar que los operandos pueden ser
incrementados, multiplicados, divididos y comparados. stas
conversiones son todas de ampliamiento.

Entonces ellas son conocidas como conversiones de promocin


aritmtica, porque los valores son promovidos a tipos ms amplios.
Las reglas que gobiernan la promocin aritmtica difiere entre
operadores unarios y binarios. Los operadores unarios operan en un solo
operando. Los operadores binarios operan en 2 valores. La figura 4.3
muestra los operadores bsicos unarios y binarios de Java.
Figura 4.3
Operadores
unarios
Operadores
binarios

++

--

&

*
^

/
|

~
%

>>

>>>

<<

Para operadores unarios, dos reglas se aplican, dependiendo en el tipo


de operando simple:

Si el operando es un byte, un short o u char, es convertido a int.


En otro caso, si el operando es de otro tipo, no es convertido.

Para operadores binarios, hay cuatro reglas, dependiendo de los tipos de


los dos operandos:

Si uno de los operandos es un double, el otro operando es


convertido a float.
Si uno de los operandos es float, el otro operando es convertido a
float.
Si uno de los operandos es un long, el otro operando es convertido
a long.
Si no, ambos operandos son convertidos a int.

Con stas reglas en mente, es possible determinar que realmente


sucede en el cdigo de ejemplo dado al inicio de sta seccin:
El short es promovido a un int y luego incrementado.
El resqueultado del paso 1 (un int) es multiplicado por el entero i.
Desde que ambos operandos sean del mismo tipo, y se tipo no
sea ms pequeo que un int, no se necesita conversin. El
resultado de la multiplicacin es un int.

Antes de dividir el float f, por el double d, f es ampliado a double.


La divisin genera un resultado de doble precisin. El resultado del
paso 2 (un int) est para comparar el resultado del paso 3 (un
double). El entero es convertido a double, y los dos opernados son
comparados. El resultado de la comparacin es siempre de tipo
boolean.
Primitivas y Casting
Con lo visto en ste capitulo, se ha mostrado que Java es perfectamente
capaz de realizar conversiones de ampliamiento en primitivas. stas
conversiones son implcitas y por detrs de escenas; usted no necesita
escribir ningn cdigo explcito para hacer que sucedan.
Casting significa direccin explcita a Java para hacer una conversin.
Una operacin de casting puede ampliar o disminuir su argumento. Para
hacer cast, solo preceda un valor con el nombre del tipo deseado entre
parntesis. Por ejemplo, las siguientes lneas de cdigo hacen un cast de
int a double:
1.
2.

int i = 5;
double d = (double)i;

Por supuesto, el cast no es necesario. El siguiente cdigo, en que el cast


ha sido omitido, podra hacer una asinacin en i, con el mismo resultado
del ejemplo anterior:
1.
2.

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.

System.out. println( s = " + s + ", b = " + b );

El mensaje de error de compilacin para la segunda lnea ser (among


other things), "Explicit cast needed to convert short to byte."),
Agregando un cast, es fcil:
1.
2.
3.

short s = 259;
byte b = (byte)s;
// explicit cast
System.out.println( b = " + b );

Cuando ste cdigo es ejecutado, el nmero 259 (binario: 100000011)


debe ser ajustado a un simple byte. Esto es logrado preservando los
bytes de ms bajo orden y descartando el resto. El cdigo tendr de
salida ste mensaje:
b=3
El bit 1 en la posicin 8 ha sido descartado, dejando nicamente 3,
como es mostrado en la figura 4.5. La conversin por reduccin puede
resultar en cambios radicales de valor; esto es porque el compilador
requiere que usted haga el cast explcitamente. El cast le dice al
compilador si, yo realmente deseo hacerlo.
Figura 4.4
0

b = (byte)s

Haciendo casting de un valor a un valor ms amplio (fig. 4.2) es


siempre permitido, pero nunca requerido; si usted omite el cast, una
conversin implcita ser efectuada a su nombre.

Sin embargo, el casting explcito puede hacer su cdigo ms leble. Por


ejemplo:
1.
2.

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:

Usted puede pasar un no booleano a cualquier otro no booleano.


Usted no puede pasar Boolean a otro tipo, ni otro tipo a Boolean.

Note que mientras el casting es ordinariamente en estrechamiento, es


perfectamente lcito cuando se efecta ampliacin. El cast es
innecesario, pero provee un poco de claridad.
Conversin de referencias a Objetos
Los valores de referencia a objetos, como los valores primitivos,
participan en asignacin, conversin, conversin por llamadas a
mtodos, y casting. (No hay promocin aritmtica de referencias a
objetos, desde que las referencias no sean operandos aritmticos). La
conversin de referencias a objetos es ms complicada que la
conversin primitiva, porque hay ms combinaciones posibles de viejos
y nuevos tipos, y ms combinaciones significan ms reglas.
La conversin de referencias, como la conversin de primitivos, toma
lugar al tiempo de compilacin, porque el compilador tiene toda la
informacin que se necesita para determinar si la conversin es legal.
Despus usted ver que ste no es el caso para el casting de objetos.
Las siguientes secciones examinan la asignacin de referencias a
objetos, llamadas de mtodos y conversiones por casting

Conversin de referencias a objetos por asignacin


La Conversin de referencias a objetos por asignacin sucede cuando
usted asigna un valor de referencia a objeto a una variable de tipo
diferente. Hay 3 clases generales de tipos de referencia a objetos.

Un tipo clase, como Button o FileWriter


Un tipo interfaz, como Cloneable o LayoutManager
Un tipo arreglo, como int[][] o TextArea[]

Generalmente hablando, la conversin por asignacin de referencias, se


ve as:
1.
2.

OldType x = new OldType ();


NewType y = x;
// conversin por asignacin de referencias

sto es el formato general de una conversin por asignacin de un viejo


tipo a uno nuevo. Desafortunadamente, el viejo tipo puede ser una
clase, una interfaz o un arreglo; el nuevo tipo puede tambin ser una
clase, interfaz o arreglo. Entonces hay 9 posible combinaciones a
considerar. La figura 4.6 muestra las reglas de los 9 casos:
Figura 4.6
OldType es una
clase

OldType es una
interfaz

OldType es un
arreglo

NewType es
una clase

OldType debe ser


subclase de
NewType

NewType debe ser


Object

NewType debe ser


Object

NewType es una
interfaz

OldType debe
implementar la
interfaz NewType

Oldtype debe ser


sub-interfaz de
NewType

NewType debe ser


Cloneable

NewType is un
arreglo

Error de
compilacin

Error compilacin

OldType debe ser un


arreglo de algunos tipos
de referencia a objetos
que puede ser convertido
a cualquier NewType

Podra ser difcil memorizar las nueve reglas de la figura 4.5,


afortunadamente, hay una regla general.
Recordar que con primitivas, las conversiones eran permitidas, dado que
eran de ampliacin widening. La nocin de ampliacin no se aplica
realmente a referencias, pero hay un principio similar. En general, la
conversin de referencias a objetos es permitida cuando la direccin de
la conversin es hacia arriba en la jerarqua de herencia, que es, el viejo
tipo debe heredar del nuevo tipo. sta regla general no cubre los 9
casos pero es til.
Las reglas para la conversin de referencias a objetos son las
siguientes:

Un tipo interfaz puede ser nicamente convertido a un tipo


interfaz o objeto. Si el nuevo tipo es una interfaz, sta debe ser
una superinterfaz del viejo tipo.

Un tipo clase puede ser convertido a un tipo clase o un tipo


interfaz. Si se convierte a una clase, el nuevo tipo ser una
superclase del viejo tipo. Si se convierte a un tipo interfaz, la vieja
clase debe implementar tal interfaz.

Un arreglo puede ser convertido a la clase Object, a la interfaz


clonable o serializable, o a un arreglo. nicamente un arreglo de
referencias a objetos puede ser convertido a un arreglo, y el viejo
tipo de elementos debe ser conversible al nuevo tipo de
elementos.

Para ilustrar stas reglas, considere la jerarqua de herencia mostrada


en la figura 4.6 (asuma que hay una interfaz llamada squeezable)

Figura 4.6
La jerarqua frutal
Object

Fruit

Lemon

Citrus

(implementa Squeezable)

Tangelo

Grapefruit

Como primer ejemplo, considere el siguiente cdigo:


1.
2.

Tangelo tange = new Tangelo();


Citrus cit = tange;

ste cdigo funciona bien, Tangelo est siendo convertida a Citrus. El


nuevo tipo es una superclase del viejo tipo, as que la conversin es
permitida.
Convirtiendo en la otra direccin (hacia abajo en la jerarqua) no es
permitida1:
1.
2.

Citrus cit = new Citrus();


Tangelo tange = cit;

ste cdigo resultar en un error de compilador


Qu sucede si uno de los tipos es una interfaz?

Recuerde: Esto no significa que usted no pueda hacerlo por casting.

1.
2.
3.

Grapefruit g = new Grapefruit();


Squeezable squee = g;
// no hay problema
Grapefruit g2 = squee;
// error

La segunda lnea cambia un tipo clase Grapefruit a un tipo interfaz. Esto


es correcto, con tal que Grapefruit implemente Squeezable. Un vistazo a
la figura 4.6 muestra que esto es de hecho el caso, porque Grapefruit
hereda de Citrus, que implementa Squeezable.
La tercera lnea es una error, porque una interfaz nunca puede ser
implcitamente convertida a cualquier tipo referencia ms que el objeto.
Finalmente, considere un ejemplo con arreglos:
1.
2.
3.
4.
5.
6.
7.
8.

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

La lnea 7 convierte un arreglo de Citrus a un arreglo de Fruti. Esto est


bien porque Fruti es una superclase de Citrus. La lnea 8 convierte en
otra la direccin y falla, porque lemon no es superclase de Citrus.
CONVERSION DE OBJETOS POR EL MTODO CALL
Afortunadamente, las reglas de conversin por el mtodo CALL de
valores de referencias a objetos son las mismas reglas descritas para la
conversin de objetos por asignacin. La regla general es que la
conversin a una superclase es permitida pero no a una subclase. Las
reglas especficas, formales fueron dadas, en una lista del bulleted en la
seccin anterior y se muestra aqu de nuevo:

Un tipo interfaz puede ser nicamente convertido a un tipo


interfaz o objeto. Si el nuevo tipo es una interfaz, sta debe ser
una superinterfaz del viejo tipo.

Un tipo clase puede ser convertido a un tipo clase o un tipo

interfaz. Si se convierte a una clase, el nuevo tipo ser una


superclase del viejo tipo. Si se convierte a un tipo interfaz, la vieja
clase debe implementar tal interfaz.

Un arreglo puede ser convertido a la clase Object, a la interfaz


clonable o serializable, o a un arreglo. nicamente un arreglo de
referencias a objetos puede ser convertido a un arreglo, y el viejo
tipo de elementos debe ser convertible al nuevo tipo de
elementos.

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.

Vector myVec = new VectorQ;


Tangelo tange = new TangeloQ;
myVec.addElement( tange );

El argumento Tange automticamente ser convertido a tipo Object.


La conversin automtica quiere decir que quien escriba la clase Vector
no tiene que escribir un mtodo por separado para cada tipo de Objeto
posible que se pueda almacenar en un vector. Por fortuna: la clase
Tangelo fue desarrollada dos aos despus de la invencin del Vector,
as que posiblemente el diseador de la clase Vector no podra escribir
cdigo del manejo especifico de Tangelo. Un objeto de cualquier clase
(incluso una arreglo de cualquier tipo) puede pasarse en el llamado
sencillo al mtodo addElement (obj del Objeto).
Casting por Referencia a Objetos
El Casting por referencia a objetos es similar al Casting primitivo: por el
uso de Cast puede pedir al compilador que le permita hacer una
conversin hacia otro tipo que de otra forma no se permitira.
Cualquier tipo de conversin que es permitida por asignacin Mtodo
Call es permitida para el cast explcito. Por ejemplo el siguiente cdigo
es aceptado:

1.
2.

Lemon lem = new Lemon();


Citrus cit = (Citrus)lem;

El Cast es legal, pero no necesario; si se omite el compilador har una


conversin de la asignacin implcita. El poder del Casting aparece
cuando explcitamente se hace cast a un tipo que no es permitido por
las reglas de conversin implcita.
Para entender como trabaja el Casting para Objetos, es importante
entender la diferencia entre Objetos y variables de referencia a Objetos.
Cada objeto (bien, casi cada objeto porque hay algunos casos oscuros)
es construido con el operador new.
El argumento para
new
determina durante todo el tiempo la clase correcta del objeto. Por
ejemplo, si un objeto es construido llamando a new Color (222, 0,
255), entonces a lo largo de la vida de ese objeto su clase ser Color.
Recuerde que los programas de Java no se tratan directamente de
objetos. Se tratan de referencias a los objetos. Por ejemplo, considere el
cdigo siguiente:
1.

Color purple = new Color( 222, 0,

255 );

La variable purple no es un objeto, es la referencia a un objeto. El


objeto reside en memoria en alguna parte de la Mquina Virtual de
JAVA. La variable purple contiene algo similar a la direccin del objeto.
Esta direccin es conocida como una referencia al objeto.
La diferencia entre una referencia y un objeto se ilustra en la figura 4.7
Figura 4.7
Referencias

b
1

Blob b = new Blob();


b es una referencia:
un valor de 32-bit
contiene la direccin
del objeto Blob

Objeto de tipo Blob en


RAM

Las referencias son almacenadas en variables, y las variables tienen


tipos que son especificados por el programador en tiempo de
compilacin. Los tipos de variables de referencia a Objetos pueden ser
clases (como Graphics o FileWriter), interfaces (como Runnable o
LayoutManager), o arreglos (como int [] [] o Vector []).
Mientras la clase de un objeto es inmutable, puede ser referenciada por
variables de muchos tipos diferentes. Por ejemplo, considere una pila.
Es construida llamando new Stack(), as que su clase realmente es
Stack. Durante varios momentos del tiempo de vida de este objeto,
puede ser referenciado por variables de tipo Stack (por supuesto), o
del tipo Vector (porque Stack hereda de Vector), o del tipo Objeto
(porque hereda todo del Objeto).
Incluso puede ser referenciada por variables de tipo Serializable, que
es una interface, porquel a Clase Stack implementa la interface de
Serializable. Esta situacin se muestra en Figura 4.8.

Serializable ser;
1

Object obj;
1

Objeto de tipo Stack in


RAM

Vector vec;
1

Stack stk;
1

El tipo de referencia a variable es obviado en tiempo de compilacin. Sin


embargo, la clase de referencia a objeto en forma semejante semejante
a la variable no puede conocerse hasta el runtime. Esta falta de
conocimiento no es una limitacin de tecnologa de Java; es el resultado
de un principio fundamental en ciencias de la computacin. La distincin
entre el conocimiento en tiempo de compilacin y conocimiento en el
runtime no es pertinente a nuestra discusin de conversiones; sin
embargo, la diferencia llega a ser importante con el casting de
referencia por valor. Las reglas para casting son un bit ms ancho que
aqullos para la conversin. Alguna de estos reglas se preocupa por el
tipo referencia y puede ser fortalecida por el copilador en tiempo de
compilacin; otras reglas se preocupan por la clase objeto y slo puede
darse durante tiempo de ejecucin.
No hay ningn escape el hecho que hay varias reglas que gobiernan el

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 es una OldType es una OldType es una Oldtype es un


array
clase
clase final
interface
non-final
NewType
Es una clase
non-final

OldType debe
extender
NewType, o
viceversa

OldType debe
extender
NewType

Siempre Bien

NewType debe
ser Object

NewType es una NewType debe


clase final
extender
OldType

OldType y
NewType debe Error de
NewType deben implementar la Compilacin
ser la misma
interfaz oldtype
clase

NewType es una Siempre bien


interface

OldType debe
implementar la
interfaz
NewType

Casi siempre
bien

NewType debe
ser Cloneable

NewType es un OldType debe


array
ser
Object

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 .

Asumiendo que el cast deseado sobrevive a la copilacin, un segundo


control ocurren en el runtime. El segundo control determina si el cast
para la clase del objeto es compatible con el nuevo tipo. Aqu la
compatibilidad significa que la clase puede convertirse segn las reglas
de la conversin presentadas en las dos secciones anteriores.
En forma sana, tenga presente que slo algunas de las situaciones
cubiertas por estas reglas normalmente se encuentra en la vida real.
(Hay casos por ejemplo, cuando no es bueno tener interfaces para
ambos tipos viejos y nuevos, pero estos casos son sumamente raros).
Unas reglas claves y algunos ejemplos deben ayudar a clarificar las
cosas. primero, simplificando con las reglas en tiempo de compilacin,
tenga presente los hechosde bajo nivel sobre casting de Oldtype a
NewType:

Cuando OldType y NewType son clases, una clase debe ser un


sub-clase de otra.

Cuando OldType y NewType son arrays, ambos arrays deben


contener la referencia al tipo (no primitivas), y debe hacer casting
legal en elementos de Oldtype a elementos de NewType.

Siempre puede hacer cast entre una interfaz y un objeto no-final.

En cuanto a las reglas de runtime, recuerde que la conversin a


NewType debe ser posible.

Las siguientes reglas claves son las ms comunes:

Si NewType es una clase, la clase de la expresin a convertirse

debe ser NewType o debe heredar de NewType.

Si NewType es una interfaz, la clase de la expresin a convertirse


debe implementar NewType.

Mire una vez ms la jerarqua de Fruit/Citrus que vio antes en este


captulo. Primero, considere el cdigo siguiente:
1.
2.
3.
4.
5.
6.
7.

Grapefruit g1, g2;


Citrus c;
Tangelo t;
g1 = new Grapefruit();
c = g1;
g2 = (Grapefruit)c;
t = (Tangelo)c;

// 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.

Grapefruit g1, g2;


Squeezable s;
g1 = new Grapefruit();
s = g1;
// convierte Grapefruit a Squeezable (bien)
g2 = s; // convierte Squeezable a Grapefruit (error de compilacin)

Este cdigo no compilar. La lnea 5 obliga convertir una interface


(Squeezable) a una clase (Grapefruit). no importa que Grapefruit lleve
a cabo Squeezable. Implcitamente convertir una interface a una clase
nunca se permite; es uno de esos casos donde se tiene que usar un cast
explcito para decirle al copilador que usted realmente sabe lo que est
haciendo. Con el cast, lnea 5 se vuelve
5.

gl = (Grapefruit)s;

Agregando el cast hace al compilador feliz. En runtime, la Mquina


Virtual Java verifica si la clase de s (qu es Grapefruit) puede ser
convertida a Grapefruit. Puede ciertamente, as que el cast se permite.
Para un ejemplo final, involucrando array, mire el cdigo siguiente:
1.
2.
3.
4.
5.
6.

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

La lnea 6 hace cast de Squeezables (s) a un array de Citruses (c). Un


cast de array es legal si el casting entre tipos del elemento array es
legal (y si los elementos son referencias de tipo no primitivas). En este
ejemplo, la pregunta es si un Squeezable (el tipo del elemento de array
s) puede hacer cast a un Citrus (el tipo elemento hace cast a array). El
ejemplo anterior mostr que ste es un cast legal.

Resumen del captulo


Los valores primitivos y referencias del objeto son tipos muy diferentes
de datos. Los dos pueden convertirse (implcitamente) o hacer cast
(explcitamente). Los cambios del tipo Primitivos se producen por:

Conversin por asignacin


Conversin por le mtodo Call
Conversin por promocin Aritmtica
Casting Explcito

Las Primitivas slo puede convertirse si la conversin extiende los datos.


Las Primitivas puede hacer recorte por casting, con tal que ni el viejo ni
el nuevo tipo sea boolean.
La referencia a Objetos puede convertirse o hacer cast; las reglas que
gobiernan estas actividades son extensas, porque hay muchas
combinaciones de casos. En general, yendo "hacia arriba" en el rbol de
herencia puede lograrse implcitamente a travs de la conversin; yendo
"hacia abajo" en el rbol se requiere casting explcito.
El cambio en la referencia a objetos puede suceder por:

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.

D. Las primitivas y la referencia a objetos pueden ser convertidas y


hechas por cast. El Casting de tipo numrico requiere control en el
runtime.
2. Cules lneas en el cdigo siguiente no compilarn?
1.
2.
3.
4.
5.
6.
7.
8.
9.

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;

3. El siguiente cdigo compilar?


1.
2.
3.

byte b1 = 2;
byte b2 = 3;
b = b1*b2;

4. En el siguiente cdigo, que tipo de variables resultan (escoja la


respuesta ms correcta).
1.
2.
3.

A.
B.
C.
D.
E.

byte b = 11;
short s = 13;
result = b * ++s;

byte, short, int, long, float, double


boolean, byte, short, char, int, long, float, double
byte, short, char, int, long, float, double
byte, short, char
int, long, float, double

5. Considere la siguiente clase:


1.
2.
3.

class Cruncher {
void crunch( int i )
{ System.out.println( "int version" ); }
void crunch( String s ) { System.out.println( "String version" ); }

public static void main( String[] args ) {


Cruncher crun = new Cruncher();
char ch = 'p';
crun.crunch( ch );
}

4.
5.
6.
7.
8.
9.

Cual de las siguientes afirmaciones es correcta (Escoja una)


A. L a Lnea 3 no compilar, porqu el mtodo en void no puede ser
sobreescrito.
B. La lnea 8 no compilar, porque no hay version de crunch() que tome
un argumento char.
C. El cdigo compilar pero habr una excepcin 8.
D. El cdigo compilar y produce la siguiente salida :
int version
E. El cdigo compilar y produce la siguiente salida :
String versin
6. Cul de las siguientes afirmaciones es correcta? (Escoja una)
A. La referencia a objeto puede ser convertida por asignacin pero no
por llamada al Mtodo.
B. La referencia a Objeto puede ser convertida por llamada al mtodo
pero no por asignacin.
C. La referencia a objeto puede ser convertida por llamada al mtodo y
por asignacin, pero las reglas que manejan esta conversin son muy
diferentes.
D. La referencia a objeto puede ser convertida por llamada al mtodo y
por asignacin, pero las reglas que manejan esta conversin son
idnticas.
E. La referencia a Objetos nunca puede ser convertida.
7. Considere el siguiente Cdigo:
1.
2.
3.
4.
5.

Object ob = new Object();


String[] strArr = new String[ 50 ];
Float floater = new Float( 3.14f );
ob = strArr;

6.
7.
8.

ob = strArr[ 5 ];
floater = ob;
ob = floater;

Cul lnea no compila?


8. Consider el siguiente cdigo:
Animal

Mammal

Dog

Cat
(implements Washer)

1.
2.
3.
4.
5.
6.

Raccoon

SwampThing

(implements Washer)

Dog rover, fido;


Animal anim;
rover = new Dog();
anim = rover;
fido = (Dog)anim;

Cul de las siguientes afirmaciones es correcta? (Escoja una)


A. La lnea 5 no compila.
B. La lnea 6 no compila.
C. El cdigo compila pero se produce un error de Excepcin en la lnea
6.
D. El cdigo compila y corre.
E. El cdigo compila y corre, pero el cast en la lnea seis no es requerido
y puede ser eliminado.
9. Considere el siguiente cdigo:

1.
2.
3.
4.
5.
6.
7.

Cat sunflower;
Washer wawa;
SwampThing pogo;
sunflower = new Cat();
wawa = sunflower;
pogo = (SwampThing)wawa;

Cul de las siguientes afirmaciones es correcta? (Escoja una)


A. La lnea 6 no compila; un cast explicito es requerido para convertir
un Cat en un Washer
B. L a lnea 7 no compila, porque no se puede hacer cast de una interfaz
hacia una clase.
C. El cdigo compila y corre, pero el cast en la lnea 7 no es requerido y
puede ser eliminado.
D. El cdigo compila pero se produce una excepcin en la lnea 7,
porque la conversin en runtime de una interfaz hacia una clase no
es permitida.
E. El cdigo compila pero se produce una excepcin en la lnea 7,
porque en runtime la clase wawa no puede ser convertida a tipo
SwampThing.
10. Considere el siguiente cdigo:
1.
2.
3.
4.
5.
6.
7.

Raccoon rocky;
SwampThing pogo;
Washer w;
rocky = new RaccoonQ;
w = rocky;
pogo = w;

Cul de las siguientes afirmaciones es correcta? (Escoja una)


A. La lnea 6 no compila, un cast explicito es requerido para convertir
Raccoon en Washer.
B. La lnea 7 no compila; un cast explicito es requerido para convertir
Washer en SwampThing.
C. El cdigo compila y corre.

D. El cdigo compila pero se produce una excepcin en la lnea 7,


porque la conversin en runtime de una interfaz hacia una clase no
es permitida.
F. El cdigo compila pero se produce una excepcin en la lnea 7,
porque en runtime la clase w no puede ser convertida a tipo
SwampThing.

You might also like