Inicio » Informática profesional. » Programación » Curso de Java » Variables referenciadas

Curso de Java

Variables referenciadas

Asociadas a objetos o instancias de una clase. Se irán estudiando durante el curso.


Inscríbete ahora y accede a 3 unidades gratis

Evalua el curso de Java y accede a las 3 unidades gratis con acceso completo al aula virtual donde podrás disfrutar de la inestimable ayuda del tutor y una gran variedad de recursos como videotutoriales, ejercicios resueltos, foros, enlaces, bibliografía, etc....


Casting o transformaciones de tipo

El casting es un procedimiento para transformar una variable primitiva de un tipo a otro, o transformar un objeto de una clase a otra clase siempre y cuando haya una relación de herencia entre ambas (este último casting es el más importante y se verá más adelante).

Dentro del casting de variables primitivas se distinguen dos clases:

  • Implícito: no se necesita escribir código para que se lleve a cabo. Ocurre cuando se realiza una conversión ancha (widening casting), es decir, cuando se coloca un valor pequeño en un contenedor grande.

Ejemplo 1:

Ejemplo 2: similar al anterior.

En cambio,

  • Explícito: sí es necesario escribir código. Ocurre cuando se realiza una conversión estrecha (narrowing casting), es decir, cuando se coloca un valor grande en un contenedor pequeño. Son susceptibles de pérdida de datos.

Ejemplo 1:

NOTA: si se sustituyera la primera línea int num1=100 por int num1=1000000, el código compilaría bien, pero habría pérdida de datos, pues el 1000000 se sale del rango de short [-32768, 32767]. Al mostrar por consola el valor se obtendría un resultado incongruente.

Ejemplo 2:

Ejemplo 3: continuación del Ejemplo 2 del casting implícito

Para que la línea

compile debe hacerse un casting explícito a long

pero no

porque, en la línea anterior, 10000000000 es considerado int, mientras que en las de arriba, double.

Dicho esto, se va a analizar un ejemplo un tanto extraño.

Ejemplo extraño:

Dado que cualquier entero, por defecto, se almacena en un int (4 bytes), con la línea anterior se pretende colocar un valor grande (el int 10) en un contenedor pequeño (una primitiva de tipo byte con capacidad para 1 byte). Esto, según lo expuesto anteriormente, precisa de casting explícito.

Pero, resulta que no hace falta, ya que el compilador, cuando se trabaja con enteros, digamos que, provoca un "casting implícito contranatura" y transforma automáticamente a byte el int 10. Ocurriría lo mismo si se trabajara con short y char.

Lo que pasa (y esto es lo que resulta un tanto extraño) es que no ocurre lo anterior con los decimales: por eso, una línea como

provoca error de compilación. Recordar que cualquier decimal, por defecto, se almacena en un double (8 bytes) y que un tipo float tiene capacidad para 4 bytes. En los decimales, el compilador no fuerza el casting implícito contranatura. De ahí que sea necesario un casting explícito a float para evitar el fallo de compilación.

NOTA: quizá se evitarían estas situaciones, si el compilador no forzara el casting implícito contranatura a byte, short o char de un int y provocara error de compilación, del mismo modo que cuando se declara un float y no se castea explícitamente. Pero, de momento, esto es lo que hay.

Código de partida para explicar el casting entre variables primitivas que almacenan datos numéricos:

Las líneas 3 y 4 almacenan al número 10 mediante una variable primitiva de tipo byte vía "casting implícito contranatura", el 3000 mediante una de tipo short, también vía "casting implícito contranatura". Lo más intuitivo es definirlas mediante un casting explícito, pero tal y como están también se puede.

Supuestamente, la línea 5, almacena el 3000000000 mediante una variable de tipo long, vía casting implícito, pero es falso. Ocurre lo que se ha comentado en el Ejemplo 2 del casting implícito: 3000000000 no es considerado como long sino como int y 3000 millones no pertenece al rango asociado a int (aprox. [-2150 millones, 2150 millones]). Si se intenta compilar, se produciría error.

Supuestamente, la línea 6, almacena el 256.5 mediante una variable de tipo float (ocupa 4 bytes en memoria), vía "casting implícito contranatura", pero, como se ha comentado en el Ejemplo extraño, es falso, ya que en decimales nunca se produce. Debe castearse explícitamente a float.

El código correcto sería:

Código fuente

 

  • Una cuestión a tener en cuenta relacionada con el casting entre variables primitivas es la siguiente:

En Java se realizan automáticamente conversiones de una variable primitiva de un tipo a otra de otro, de igual o mayor precisión, siempre y cuando se respeten los rangos asociados al tipo convertido.

La precisión depende del número de bytes ocupados en memoria y del rango de valores asociado: a mayor número de bytes ocupados, mayor precisión y mayor rango asociado.

Así, pasar de byte a short, de short a int, de byte a int, … es automático siempre y cuando el entero a convertir no supere el rango del tipo convertido; en definitiva, pasar de una variable primitiva de un tipo de la cadena de la siguiente línea a otra que se encuentre a su derecha es automático.

byte-->short-->int-->long-->float-->double

Así, por ejemplo, si un método necesita un long como argumento y se le pasa un entero perteneciente al rango de int, promociona automáticamente a long y no es necesario casting.

En cambio, si se le pasa un entero que se sale fuera del rango de int, es necesario realizar un casting para que la llamada al método no provoque error al compilar.

Un ejemplo de esto ocurre con el método estático de java.lang.Thread "void sleep(long retardo)" que introduce un retardo en la ejecución del código, coincidente con el entero, en milisegundos, que se le pasa al argumento. Este método se estudiará más adelante.

Por consola:

Hola

-- Después de tres segundos --

Adios

En cambio, si se sustituye

Thread.sleep(3000) por Thread.sleep(3000000000)

no compila ya que el entero que se le pasa no pertenece al rango de int y no puede promocionar a long automáticamente.

Para que compile es necesario hacer un casting explícito:

Thread.sleep(3000000000L)

 

  • Para finalizar con el casting entre primitivas, conviene tener en cuenta lo siguiente:
  • No es posible realizar casting entre una variable primitiva  booleana y cualquier otra variable primitiva.
  • Sí es posible realizar casting entre una variable primitiva char y una variable primitiva que almacene enteros.

Ejemplo:

Código fuente

Por consola:

ñ

ñ


Inscríbete ahora y accede a 3 unidades gratis

Evalua el curso de Java y accede a las 3 unidades gratis con acceso completo al aula virtual donde podrás disfrutar de la inestimable ayuda del tutor y una gran variedad de recursos como videotutoriales, ejercicios resueltos, foros, enlaces, bibliografía, etc....


Si desea obtener un acceso sin restricciones a los contenidos del curso de Java y disfrutar de todas las herramientas del aula virtual (Videos explicativos streaming, acceso a los foros, chat, ejercicios resueltos, la ayuda del tutor, audioconferencia, estudio de grabación, test y actividades de autoevaluación, etc...) puede inscribirse completamente gratis y comenzar a realizar de forma inmediata el curso.