Oracle certified professional java se 6 programmer 3

50 %
50 %
Information about Oracle certified professional java se 6 programmer 3

Published on March 9, 2014

Author: PabloGaleanaBailey

Source: slideshare.net

México Distrito Federal a 08 de Marzo de 2014 Autor: Pablo Galeana Bailey Cualquier duda y/o comentario quedo a sus órdenes para alguna asesoría o recomendación para mejorar el presente material. Email: knoppixpgb@gmail.com Capítulo 3 - Asignaciones 1. Stack y Heap -Rápido repaso La mayor parte de las variables, métodos y objetos en un programa Java se alojan en dos memorias diferentes: Stack o Heap. Por ahora nosotros vamos a tratar tres tipos de cosas: variables de instancia, variables locales y objetos:  Las variables de instancia y los objetos se almacenan en la memoria Heap.  Las variables locales se colocan en la memoria Stack.

Ejemplo un programa Java y la manera en que se almacenan en la Stack o Heap: En la siguiente figura se visualiza donde se almacena cada elemento: 2.1. Valores literales para todos los tipos Primitivos Un literal primitivo es simplemente una representación en código de los tipos de datos primitivos, en otras palabras, un número entero, punto flotante, booleano o carácter. Los siguientes ejemplos son literales primitivos:

 Enteros Hay tres maneras de representar un entero en el lenguaje Java: decimal, octal y hexadecimal. La mayoría de las preguntas son con literales enteros en decimal, pero las pocas que usan octal o hexadecimal son necesarias estudiársela.  Decimales En el lenguaje Java se representan, sin prefijo de ningún tipo, como lo siguiente:  Octales Los enteros octales solo usan números del 0 al 7. En Java, se representan colocando un 0 delante del número, como vemos a continuación: Un número octal puede tener 21 dígitos no incluyendo el cero del comienzo. Si ejecutamos el anterior código, nos mostrara lo siguiente: Octal 010 = 8  Hexadecimales Los números hexadecimales son construidos usando 16 símbolos diferentes. Los números del 10 al 15 son caracteres alfabéticos que representan a los dígitos. Los diferentes símbolos son: 0123456789abcdef Java aceptara mayúsculas o minúsculas para los dígitos extras (uno de los pocos lugares de Java que no es case-sensitive). Se permiten 16 dígitos en un hexadecimal, sin contar el prefijo 0x o el sufijo opcional L. Todas las siguientes asignaciones de decimales son legales:

La X = 1 salida y = sería 2147483647 la z = siguiente: -559035650 No te dejes engañar por las minúsculas y mayúsculas en un dígito hexadecimal, 0XCAFE y 0xcafe son ambos legales y tienen idéntico valor. Los tres literales enteros son definidos como int por defecto, pero también serán especificados como long colocando un sufijo de L o l detrás del número:  Punto-flotante Los números en punto-flotante son definidos como un número, un símbolo decimal (punto) y mas números representando la fracción. double d = 11301874.9881024; En el ejemplo anterior, el número 11301874.9881024 es el valor literal. Los puntoflotante son definidos por defecto como doublé (64 bits), así que si tú quieres asignar un punto-flotante a una variable de tipo float (32 bits), entonces debes poner el sufijo L o l al número: También podríamos opcionalmente poner D o d cuando es double, pero no es necesario porque es su tipo por defecto: Si en vez del carácter punto ponemos una coma el código no compilara:  Booleanos Un booleano puede valer true o false únicamente. Aunque en C es común usar números para representar true o false, esto no es posible en Java. Estar atento a las preguntas en las que un número este en el lugar que debería estar un booleano, por ejemplo como en el siguiente código:

 Carácter Un carácter está representado por un único carácter entre comillas simples. También se puede escribir el valor UNICODE del carácter, usando la notación UNICODE con u como prefijo. Recuerda, los caracteres son enteros de 16 bits sin signo. Los siguientes ejemplos son todos legales: Y los siguientes son erróneos y producen errores de compilación: También pueden usar un código de escape si tú quieres representar un carácter que no pueda escribirse en un literal, incluyendo los caracteres fin de línea, nueva línea, horizontal tab, backspace y comillas simples.  Valores literales para String Un literal String es la representación en código de un objeto String. Por ejemplo, lo siguiente son dos formas diferentes de representar un literal String: Aunque los String no son primitivos, están incluidos en esta sección porque pueden ser representados como literales. Es el único tipo no primitivo junto con el array que tiene una representación literal: 2.2. Asignación de operadores Las variables son solo bits, al que se le asigna un tipo. Pueden ser int, double, Button e incluso String[]. Para los primitivos, los bits representan un valor numérico. UN byte con valor 6, por ejemplo, significa que el patrón en la variable es 00000110, representando los 8 bits. Un variable referenciando a un objeto es solo una variable de referencia. Una variable de referencia contiene bits que representan la manera de poder

obtener el objeto. Si la variable de referencia no tiene asignado un valor, o a sido almacenado explícitamente el valor de null, la variable se representa con null. Por ejemplo: Aquí podemos ver que La variable Button b no está referenciando a ningún objeto.  Asignaciones Primitivos El signo igual (=) es usado para asignar un valor a una variable y es llamado signo de asignación. Actualmente hay 12 operados de asignación, pero solo entran en el examen los cinco usados más comúnmente y estos se cubrirán en el Capítulo 4. Puedes asignar una variable primitiva usando un literal o el resultado de una expresión. Como podemos ver a continuación: El punto más importante que debemos recordar es que un literal entero (como 7) es siempre implícitamente un int. El siguiente código es legal: Este código es legal porque el compilador automáticamente limito el valor del literal a un byte. En otras palabras, el compilador hizo un casting. El siguiente código es idéntico al anterior: Un entero literal es siempre un int, pero aún más importante es que el resultado de una expresión que envuelva tamaños int o más pequeños es siempre un int. Es decir, si sumo dos bytes obtendré un int (incluso si esto bytes son diminutos), si multiplico un int y un short obtengo un int, si divido un short entre un byte obtendré un int,....etc. Ejemplo: La última línea no compilara. Obtendremos un error como el siguiente: TestBytes.java:5: possible loss of precision found : int required: byte byte c = a + b; Estamos intentando asignar la suma de dos bytes a otra variable byte, el resultado (11) definitivamente fue lo suficientemente pequeño como para caber en un byte, pero el compilador no tuvo cuidado. Para que compilase deberíamos haber hecho un casting explícitamente.

 Casting primitivos Hacer un casting te permite convertir valores primitivos desde un tipo a otro. Los casting pueden ser implícitos o explícitos. Un casting implícito significa que no tienes que escribir en código el casting, la conversión se provoca automáticamente. Un valor largo en un contenedor pequeño requiere un casting explicito, donde le indiques al compilador que tu asumes toda la responsabilidad de perdidas. Primero veremos castings implícitos. A continuación unos castings explícitos: Los valores enteros pueden ser asignados a una variable double sin casting explicito. Las siguientes líneas demuestran esto: En la sentencia anterior, un double esta inicializado con un valor long. El casting no es necesario porque un double puede contener cualquier información que un long pueda almacenar. Si, sin embargo, queremos asignar un valor double a un tipo entero, nosotros estamos intentando una reducción de conversión y el compilador lo sabe: Si nosotros intentamos compilar el anterior código, obtendremos un error similar al siguiente: %javac Casting.java Casting.java:3: Incompatible type for declaration. Explicit cast needed to convert double to int. int x = 3957.229; illegal 1 error Para que esto funcione, debemos hacer un casting de número en punto flotante a entero.

Al hacer el casting pierdes todo la parte decimal y el resultado sería: int x = 3957 Es permitido hacer un casting de un tipo de número largo, como long, dentro de un tipo de número más pequeño, como puede ser byte. Fíjate en lo siguiente: El código anterior compilara y se ejecutar bien. Pero qué pasa si el valor long es mayor que 127 (el mayor número que un byte puede almacenar). Vamos a modificar el código: El código compilara bien y cuando nosotros ejecutemos obtendremos lo siguiente: %java Casting The byte is -126 No obtendremos un error en tiempo de ejecución, incluso cuando el valor que está siendo reducido es demasiado grande para el tipo. Si el bit mas a la izquierda (el bit de signo) en el byte (o en cualquier entero primitivo) ahora pasa a ser un uno, el primitivo tendrá un valor negativo.  Asignando números Punto-Flotante Los números en punto-flotante implícitamente son double (64 bits), no un float. Así que el literal 32.3, es considerado un double. SI intentas asignar un double a un float, el compilador sabrá que tú no tienes suficiente espacio en un contenedor float de 32 bitas para mantener la precisión de un double de 64 bits. El siguiente código parece bueno, pero no compilara. Puedes ver que 32.3 podría ajustarse bien a una variable de tamaño float, pero el

compilador no te lo permite. Con el fin de asignar un literal punto flotante a una variable float, tú debes hacer un casting o poner al final del número la letra f. Las siguientes asignaciones compilaran:  Asignación de un literal más grande que la variable También obtendremos un error de compilación si intentamos asignar un valor literal que el compilador sabe que es mayor que el tamaño de la variable. El anterior código da un error TestBytes.java:5: possible loss found : required: byte a similar of = al siguiente: precision int byte 128; Podemos arreglarlo con un casting: Para asignarle 128 a un byte debes hacerle un casting de manera explícita, pero la asignación será de -128. Haciendo el casting solo le decimos al compilador que estamos de acuerdo con la asignación. Esto nos lleva a la asignación de operador compuesto. El siguiente código compilara: Y es equivalente a: El operador de asignación compuesto += permite sumar el valor de b, sin poner un casting explicito. De hecho, +=,-=,* y / ponen el casting de manera implícita.  Asignación de una variable primitiva a otra variable primitiva Al asignar una variable primitiva a otra, los contenidos de la variable de la derecha son copiados. Por ejemplo: En este punto, "a" y "b" tienen idéntico contenido (en otras palabras, idéntico valor), pero si cambiamos el contenido de alguna de ellas, la otra no se verá afectada. Ejemplo:

La salida del anterior programa es: %java a = a = 10 after change ValueTest 10 to b El punto clave que debemos comprender es que siempre después de asignar a una variable otra, las variables no se refieren al mismo lugar de memoria. Las variables "a" y "b" son copias idénticas.  Asignación de variables de referencia Tú puedes asignar un nuevo objeto creado a una variable de referencia al objeto como: La línea anterior tiene tres cosas claves:  Crear una variable de referencia denominada "b", de tipo Button.  Crear un nuevo Button en la memoria Heap.  Asignar el nuevo objeto Button creado a la variable b. También se puede asignar null a una variable de referencia a un objeto, que simplemente significa que la variable no está referenciando a ningún objeto: La línea anterior crea espacio para la variable de referencia de tipo Button, pero no crea un objeto Button. Se puede usar una variable de referencia para referirse a cualquier objeto que sea una subclase del tipo de la variable de referencia, como podemos ver en lo siguiente:

La regla es que puedes asignar una subclase del tipo declarado, pero no una superclase. Un objeto Bar tiene las garantías de poder hacer algo que pueda hacer Foo, de modo que cualquiera con una referencia Foo puede invocar los métodos aunque el objeto es en realidad un Bar. En el código anterior Foo tiene un método doFooStuff() que alguien con una referencia Foo podría tratar de invocar. Si el objeto referenciado por la variable Foo es en realidad un Foo, no hay problemas. Pero tampoco hay problemas si el objeto es un Bar, ya que desde Bar heredamos el método doFooStuff(). No se podría hacer a la inversa, si alguien tiene una referencia Bar, puede invocar al método doBarStuff(), pero si el objeto es un Foo, no sabría cómo responder. 2.3. Ámbito de Variable Vamos a empezar por la estructura de la siguiente clase:

Al igual que con las variables en todos los programas Java, las variables en este programa (s, x, x2, x3, y y z) tienen un ámbito:  s es una variable estática.  x es una variable de instancia.  y es una variable local (algunas veces denominada variable de método local).  z es una variable bloque.  x2 es una variable de inicialización de bloque, un tipo de variable local.  x3 es una variable de construcción, un tipo más de variable local. Existen cuatro ámbitos básicos.  Las variables estáticas tienen el mayor ámbito, son creadas cuando la clase es cargada y viven siempre y cuando la clase este cargada en la JVM.  Las variables de instancia son las siguientes que tienen mayor vida, son creadas cuando una nueva instancia ha sido creada y viven hasta que la instancia es eliminada.  Las variables locales, viven durante el tiempo que el método está en la memoria Stack. Sin embargo, pronto veremos que las variables locales pueden estar vivas estando fuera del ámbito.  Las variables de bloque viven solo durante la ejecución del bloque de código. Un error común sucede cuando una variable es shadowed (sombra) y dos ámbitos se solapan. Más adelante tendremos más detalles de shadowing. La razón más común para los errores de ámbito es cuando accedes a una variable que no está en el ámbito. Ejemplo:  Intentando acceder a una variable de instancia desde un contexto estático (normalmente desde main()).  Intentando acceder a una variable local desde un método anidado. Cuando un método, por ejemplo go(), invoca a otro método, go2(), el método go2() no tiene acceso a las variables locales de go(). Mientras go2() se esté ejecutando, las variables locales de go() siguen vivas, pero están fuera del ámbito. Cuando go2() se termine, será eliminado de la memoria Stack y go() reanudara su ejecución. Una vez llegados a este punto, todas las variables declaradas previamente volverán a estar en el ámbito.

Por ejemplo:  Intentando hacer uso de una variable de bloque después de que el código de bloque se haya terminado. Es muy común declarar y usar una variable dentro de un bloque de código, pero ten cuidado de no intentar usar la variable una vez el bloque haya terminado: En los dos ejemplos anteriores, el compilador manda error: cannot find symbol La variable a la que está intentando acceder, podría haber sido valido en otra parte del código (como por ejemplo una línea de código anterior) o no tiene en la memoria dicha variable. 2.5. Variables de instancia de tipo primitivo y Object Las variables de instancia (también llamadas variable miembro) son aquellas definidas en el nivel de la clase. Esto significa que la declaración de la variable no se hace dentro de un método, constructor o cualquier otro bloque inicializador. Las variables de instancia son inicializadas con un valor por defecto cada vez que una nueva instancia es creada, aunque podrá ser sometido a un valor explicito después de que el superconstructor del objeto se haya completado.

La siguiente tabla muestra los valores por defecto para los tipos primitivos y Object. Tipo variable Objeto referencia float, double boolean char byte, short, int, long Valor por defecto null(sin referenciar cualquier objeto) 0.0 false 'u0000' 0 2.6. Instanciar Variables Primitivas En el siguiente ejemplo, la variable year de tipo entero es definida como un miembro de clase ya que esta dentro de las llaves iníciales de la clase y no dentro de las llaves de un método: Cuando empieza el programa, le da un valor cero a la variable year, por defecto el valor para variables de instancias primitivas. 2.7. Instanciar Variables de referencia a Objetos Las referencias de Objetos que no están inicializadas son completamente diferentes. Fíjate en el siguiente código: compilara bien, la salida será: The Este title is código null La variable "title" no ha sido inicializada explícitamente con un String, así que el valor de la variable de instancia es null. Recordar que nulo no es lo mismo que

un String vacío (""). Un valor nulo significa que la variable no está referenciando a ningún objeto en la memoria Heap. La siguiente modificación del código se ejecutará con errores: Al ejecutar la clase Book, producirá lo siguiente: Exception in thread "main" at java.lang.NullPointerException Book.main(Book.java:9) El error es porque la referencia de la variable "title" no apunta a un objeto. Podemos comprobar haber si el objeto ha sido inicializado usando la palabra clave null, así como vemos en el siguiente código: Ten cuidado en el examen donde deberías tener que rastrear a través del código para encontrar si una referencia a objeto tendrá un valor nulo. En el anterior código, por ejemplo, buscas la declaración de la variable de instancia title, veras que no hay inicialización explicita, reconoces que la variable title tendrá el valor por defecto null y luego darse cuenta que la variable "s" también tendrá un valor null. Recordar, el valor de "s" es una copia del valor de "title", así que su "title" es una referencia nula, "s" también lo será. 2.8. Variables de instancia Array Los elementos de un array siempre, siempre obtienen valores por defecto, independientemente de donde el array haya sido declarado o instanciado. Si inicializamos un array, los elementos serán igual a null si no están inicializados individualmente con valores.

Ejemplo: indicará que los 100 enteros en el array son La iguales salida a cero. 2.9. Variables locales (Stack, automatic) Primitivas y objetos  Variables locales primitivas El entero "year" está definido como una variable automática porque se encuentra dentro de las llaves de un método. Las variables locales, incluyendo las primitivas, siempre deben ser inicializadas antes de intentar usarlas (aunque no necesariamente en la misma línea de código). Si intentas usar una variable primitiva sin inicializar, obtendrás un error del compilador: Al compilar produce una salida similar a la siguiente: %javac TimeTravel.Java TimeTravel.java:4: Variable year may not have been initialized. System.out.println("The year is " + year); 1 error Para corregir nuestro código, le debemos dar al entero "year" un valor. En este ejemplo actualizado, declaramos la variable en una línea diferente a la inicialización, que es perfectamente válido:

Puedes declarar una variable local mientras no uses un error might not similar have dicha variable. Observar el siguiente ejemplo: El compilador TestLocal.java:9: producirá variable x al been siguiente: initialized Debido a que el compilador no puede indicarte ciertos problemas, algunas veces necesitas inicializar tu variable fuera del bloque condicional.  Variables Locales de Referencias a Objetos Las referencias a objetos, también, se comportan de diferente manera cuando se declara en un método en lugar de declararlas como variables de instancia. Para el compilador, null es un valor. No puedes usar el operador punto (.) en una referencia con valor null, ya que no referencia ningún objeto, una referencia con valor null no es lo mismo que una referencia sin inicializar. Las referencias declaradas localmente no pueden hacer una comprobación de nulos antes de usarlo, a menos que inicialices de manera explícita la variable local a null. Ejemplo:

El resultado de la compilación del código da un error similar al siguiente: %javac TimeTravel.java TimeTravel.java:5: Variable date may not have been initialized. if (date == null) 1 error Las referencias que son variables de instancia siempre obtienen un valor por defecto null, hasta que implícitamente se inicialice con otra cosa. Las referencias locales no obtienen un valor por defecto, en otras palabras. no son nulas. Hay que establecer explícitamente las referencias con el valor null, hasta tu estar listo para inicializarla con otra cosa. La siguiente variable local compilara apropiadamente:  Variables Locales Arrays No necesitas inicializar explícitamente los elementos de una array. Lo hemos dicho anteriormente: los elementos de los arrays obtienen sus valores por defecto independientemente de si el array es declarado como una instancia o como una variable local. El objeto array no será inicializado si es declarado localmente. En otras palabras, debes explícitamente inicializar un array referencia si es declarado y usado dentro de un método, pero en el momento de construir un objeto array. 2.10. Asignando una variable referencia a otra Los contenidos de una variable de referencia son un patrón de bits, así que si asignas la variable de referencia "a" a la variable de referencia "b", el patrón de bits de "a" es copiado y almacenado en "b". Si asignamos una instancia existente de un objeto a una nueva variable de referencia, ambas tendrán el mismo patrón de bits (un patrón de bits referenciando a un objeto específico de la memoria Heap.

Ejemplo: Un objeto Dimension es declarado e inicializado con un "width" con valor 5 y un "height" con valor 10. Después, Dimension "b" es declarada y asignada el valor de "b". Solo hay un objeto Dimension, el que ambas variables "a" y "b" hacen referencia. Finalmente, la propiedad height es cambiada usando la referencia "b". La salida es: %java ReferenceTest a.height = 10 a.height = 30 after change to b De esta salida, podemos sacar una conclusión que ambas variables se refieren a la misma instancia del objeto Dimension. Cuando hacemos un cambio en "b", el cambio también se reflejara para "a". Una excepción a la manera de asignar una referencia a objeto es String. Los objetos String son inmutables. Ejemplo: La %java y y salida String String = = es: StringTest Java Java Como se puede ver, aunque "y" hace referencia al mismo objeto que "x", cuando nosotros cambiamos x, no cambia "y". Para cualquier tipo de objeto, donde dos referencias apuntan al mismo objeto, si una referencia es usada para cambiar el objeto, ambas referencias verán los cambios ya que solo existe un objeto. Pero

cada vez que hagamos cualquier cambio a un String, la VM actualizara la variable de referencia para referirse a otro objeto diferente. La razón por la que no podemos decir seguro que se crea un objeto nuevo es porque hay un pool de String, que veremos más en profundidad en el Capítulo 6. Necesitas entender que sucede cuando usas una variable de referencia String para modificar un String:  Un nuevo String es creado (o encuentra un String en el pool de String), dejando el original String sin modificaciones.  La referencia usada para modificar el String (hacer un nuevo String modificando una copia del original) es entonces asignada al nuevo objeto String. Así que cuando decimos No cambias el objeto String original creado en la línea 1. Cuando la línea 2 se acaba, ambos "t" y "s" hacen referencia al mismo objeto String. Pero cuando la línea 3 se ejecuta, se crea un nuevo objeto String. 3.1. Pasando referencias a objeto Cuando pasamos una variable objeto a un método, debemos tener en cuenta que estamos pasando la referencia al objeto y no el objeto en sí. Recordar que una variable referencia contiene bits que representa la manera de obtener un objeto específico de la memoria Heap. Lo más importante que debemos recordar es que no estamos enviando la variable de referencia actual, sino más bien una copia de la variable de referencia. Una copia de una variable significa obtener una copia de los bits de la variable, así cuando pasemos una variable referencia, estaremos pasando una copia de los bits. En otras palabras, el llamador y el método llamado tiene idénticas copias de la referencia y ambos se refieren al mismo objeto de la Heap. Para el siguiente ejemplo, usaremos la clase Dimension del paquete java.awt:

Cuando ejecutamos esta clase, podemos ver que el método modify() fue capaz de modificar el objeto original Dimension creado en la línea 4. C:Java ProjectsReference>java ReferenceTest Before modify() d.height = 10 dim = 11 After modify() d.height = 11 Fíjate cuando el objeto Dimension es pasado al método modify(), cualquier cambio que se produzca dentro del método se está realizando sobre el objeto cuya referencia fue pasada. En el ejemplo anterior, ambas variables de referencia d y dim apuntan al mismo objeto.  ¿Java utiliza semánticas paso por valor? Java es actualmente Paso Por Valor para todas las variables en ejecución dentro de una sola VM. Paso por Valor significa pasar el valor de una variable. Y esto significa, pasar la copia de la variable. NO hay diferencia si estas pasando primitivos o variables de referencia, siempre pasaras una copia de los bits de la variable. Así para una variable primitiva, tú pasaras una copia de los bits que representan el valor. Por ejemplo, si tú pasas una variable entera con el valor 3, tú estarás pasando una copia de los bits que representan al número 3. El método llamado entonces obtiene su propia copia del valor para hacer con él lo que quiera. Y si estas pasando una variable referencia a objeto, estarás pasando una copia de los bits que representan la referencia a un objeto. Por ejemplo, en el siguiente fragmento de código, Reasignando g no reasignas f. Al final del método Bar() se han creado dos objetos Foo uno referenciado por la variable f y una referenciado por la variable local g. Debido a que el método doStuff() tiene una copia de la variable de referencia, tiene una manera de obtener el objeto original Foo, por ejemplo llamando al método setName(). Pero el método doStuff() no tiene manera de obtener la variable de referencia f. Así que doStuff() puede cambiar el valor del objeto al que hace referencia f, pero no puede cambiar el contenido actual (patrón de bits) de f. En otras palabras, doStuff() puede cambiar el estado del objeto al que hace referencia la variable, pero no cambiar la referencia de f para que apunte a un objeto diferente.

3.2. Pasando variables primitivas Observar que sucede cuando una variable primitiva es pasada a un método: En este simple programa, la variable a es pasada a un método llamado modify(), que incrementa la variable sumándole uno. La salida será algo parecido a esto: Before modify() a = 1 number = 2 After modify() a = 1 Fíjate como a no cambia después de haber pasado por el método, Recordar, lo que se le pasa al método es una copia de a. Cuando una variable primitiva es pasada a un método, es pasada por valor, que significa pasar la copia de los bits de la variable. El mundo de las variables ocultas El efecto de Shadowing es ocultar la variable previamente declarada de tal manera que parezca como si estuvieses utilizando la variable oculta, pero tú estarás usando la variable "shadowing". Tú puedes "ocultar" una variable declarando una variable local con el mismo nombre, ya sea directamente o como parte de un argumento:

El código anterior parece cambiar la variable de instancia "size" en el método changeIt(), pero aunque changeIt() tiene un parámetro llamado size, la variable local size es modificada mientras la variable de instancia size permanece intocable. Ejecutando la clase obtendremos la salida: %java Foo size = 7 size in changeIt is 207 size after changelt is 7 La cosa se pone más interesante cuando la variable oculta es una referencia a objeto, en lugar de una primitiva: La salida f.myBar.barNum myBar.barNum myBar.barNum f, myBar. del in in barNum código anterior is changelt is changeIt is now after changeIt is es: 28 99 420 99 Puedes ver que la variable "shadowing" (el parámetro local myBar en changeIt()) puede afectar a la variable de instancia, porque el parámetro myBar recibe una referencia al mismo objeto Bar. Pero cuando el local myBar es reasignado a un nuevo objeto Bar, el cual modificaremos usando el valor barNum, la variable de instancia original de Foo no está modificada. 4. Objetivo de Certificación 1.3 - Array declaración, construcción e inicialización 1.3 Desarrollar código que declare, inicialice y use tipos primitivos, enumerados, arrays y objetos como estáticos, de instancia y como variables locales. Además, usar identificadores legales para los nombres de variables.

4.1. Declarando un array Los arrays se declaran indicando el tipo de elementos que contendrá, que puede ser un objeto o un primitivo, seguido de corchetes a la izquierda o a la derecha del identificador.  Declarando un array de primitivos  Declarando un array de referencias a objetos Cuando se declara una referencia array, siempre se debe poner los corchetes justo después de declarar el tipo, en lugar de después del identificador (nombre de la variable). Esto facilitara la lectura del código. También se pueden declarar un array multidimensional, que es simplemente un array de arrays. Esto se puede hacer de la siguiente manera: El segundo ejemplo que tenemos unos corchetes antes del identificador y otro después. Esto es perfectamente legal para el compilador, demostrando una vez más el hecho de que aunque sea legal no significa que sea correcto. Nunca es legal incluir el tamaño del array en la declaración. El código anterior no compilara. Recordar, la JVM no asigna espacio hasta que se instancia al objeto array. 4.2. Construyendo un array Construir un array significa crear el objeto array en la memoria Heap (donde viven todos los objetos) haciendo un "new" sobre el tipo array. El tamaño del array es el número de elementos que el array contendrá.  Construcción Array Unidimensional La manera más sencilla de construir un array es usando la palabra "new" seguido del tipo de array, con unos corchetes especificando cuantos elementos del tipo contendrá el array. Ejemplo de la construcción de un array de tipo int. El anterior código coloca un nuevo objeto en la memoria Heap (un objeto array que contendrá cuatro elementos) donde cada elemento contendrá un int con el valor por defecto 0). Lo que le diríamos al compilador es:"Crea un objeto array que contendrá 4 enteros y asignarle la variable de referencia llamada testScores.

También, estableceremos cada elemento entero a 0." La siguiente figura nos muestra el array testScores en la memoria Heap, después de la construcción. También se puede declarar y construir un array en una sola sentencia: Esta única sentencia genera el mismo resultado que las dos sentencias que vimos anteriormente. Los arrays de tipo Objeto pueden ser declarados de la misma manera. Después de la sentencia anterior, no existen aún objetos Thread. Recuerda, los arrays deben siempre indicar su tamaño a la hora de construirlos. La JVM necesita el tamaño para asignar el apropiado espacio en la memoria Heap para el nuevo objeto array. Nunca es legal hacer lo siguiente: Así que no hacerlo y si tú lo ves en el examen ve directamente a la respuesta Compilation Failed!  Construcción Array Multidimensional El siguiente código declara y construye un array bidimensional de tipo entero: Fíjate que solo los primeros corchetes llevan el tamaño. Esto es aceptable en Java, ya que la JVM solo necesita saber el tamaño del objeto asignado a la variable myArray. La siguiente figura muestra un array multidimensional en la memoria Heap.

4.3. Inicializando un array Las "cosas" en el array son los elementos del array y pueden ser primitivos (2,x,false) o objetos referenciados por una variable de referencia en el array. Si tienes un array de objetos (al contrario que los primitivos, el array no contiene los objetos, pero en cambio tiene una referencia al objeto. Los elementos individuales en un array pueden ser accedidos con un índice numérico. El índice numérico siempre empieza en 0, así que para un array de 10 elementos el índice que lo recorrería iría desde 0 a 9. Ejemplo: Nosotros tenemos un objeto array en la memoria Heap, con tres referencias null de tipo Animal, pero nosotros no tenemos ningún objeto Animal. El próximo paso será crear algún objeto Animal y asignárselo a alguna posición del array: Este código coloca tres nuevos objetos Animal en la memoria Heap y los asigna a las tres posiciones en el array pets. Un array bidimensional puede ser inicializado como veremos a continuación.

 Inicializando elementos en un bucle Los objetos array tienen una única variable pública, length que te da el número de elementos de un array. El valor del último índice es siempre uno menos que el tamaño. Por ejemplo, si el tamaño de un array es 4, el valor de índices va desde 0 hasta 3. A menudo, tu veras inicializar elementos de array en un bucle como podemos ver a continuación: La variable length nos da el número de elementos de un array, pero no nos da el número de elementos que han sido inicializados. 4.4. Declarando, construyendo e inicializando en una línea Puedes usar dos diferentes sintaxis shortcuts de especificar array para inicializar y construir en una sola sentencia. 1.- La primera se usa para declarar, crear e inicializar en una sola sentencia como la siguiente: La línea dos en el anterior código hace 4 cosas:  Declara una variable de referencia de tipo array entero llamado dots  Crea un array entero con un tamaño de 3  Rellena el array con los valores 6,9 y 8  Asigna el nuevo objeto array a la variable de referencia dots El tamaño está determinado por el número de comas entre las llaves. El siguiente código largo es funcionalmente equivalente al anterior:

Con referencias de objetos trabaja de la misma forma que con primitivas. El anterior código crea un array Dog, referenciado por la variable myDogs, con tamaño 3. Le asigna un objeto Dog creado previamente (asignado a la variable puppy) al primer elemento del array. También crea dos nuevos objetos y los asigna a los dos elementos restantes. La siguiente figura muestra el resultado. También podemos usar la sintaxis corta con arrays multidimensionales como los siguientes: El anterior código crea un total de 4 objetos en la memoria Heap. Primero, un array de enteros es construido (el objeto que será asignado a la variable de referencia scores). El array scores tiene un tamaño de 3, derivado del número de comas entre las llaves exteriores. Cada uno de los tres elementos en el array scores es una variable de referencia a un array entero, así que los tres enteros arrays son construidos y asignados a los tres elementos en el array scores. El tamaño de cada uno de los elementos es derivado del número de comas que hay entre las llaves internas. Por ejemplo, el primer array tiene tamaño 4, el segundo 2, y el tercero 2. Finalmente los tres elementos del array scores son inicializados con los valores que tienen entre llaves. El siguiente código muestra los valores de algunos de los elementos en este array bidimensional:

4.5. Construyendo e inicializando un array anónimo 2.- El segundo shortcut es denominado "anónima creación de array" y puede ser usada para construir e inicializar un array, y entonces asignar el array a una variable de referencia array declarada previamente. El anterior código crea un nuevo array entero con tres elementos, inicializa los elementos con los valores 4,7 y 2 y entonces asigna el nuevo array a la variable de referencia testScores declarada previamente. Nosotros la llamamos creación anónima de array porque no necesitamos asignar el nuevo array a nada. Ejemplo : 4.6. Arrays de primitivos Ejemplo: 4.7. Arrays de referencias a objetos Si el tipo que se declara en un array es una clase, puedes poner objetos de cualquier subclase del tipo declarado en el array. Por ejemplo, si Subaru es una subclase de Car, tú puedes poner tanto objetos Subaru como objetos Car dentro del array de tipo Car, como podemos ver a continuación:

Los elementos en un array Car son nada más que variables de referencia de Car. Así que cualquier cosa que pueda ser asignada a una variable de referencia puede ser legalmente asignada a un array de tipo Car. Si el array es declarado como tipo una interfaz, los elementos del array pueden referirse a cualquier instancia de cualquier clase que implemente la interfaz declarada. El siguiente ejemplo nos muestra un array donde el tipo es una interfaz: La conclusión es: Cualquier objeto que pase el test "IS-A" para el tipo declarado en el array, puede ser asignado a un elementos del array. 4.8. Asignaciones de referencias de array para Arrays Unidimensionales Para el examen, necesitas saber asignaciones legales e ilegales para variables de referencia array. El siguiente código nos muestra asignaciones legales e ilegales de asignaciones para arrays primitivos:

Es difícil asumir que aunque una variable de tipo byte, short o char puede ser explícitamente promocionada y asignada a un entero, un array de cualquiera de estos tipos no se puede asignar a un array de enteros. Los arrays que contienen referencias a objetos, al contrario que los primitivos, no son tan restrictivos. Ya que tú puedes poner un objeto Honda en un array de Car (ya que Honda extiende de Car), veamos lo en un ejemplo: Aplicar el test IS-A ayuda a ver si es legal o ilegal la asignación. Las reglas para arrays donde es tipo es una interfaz son iguales que con las clase. Un array declarado con un tipo interfaz puede referenciar un array de cualquier tipo que implemente la interfaz. Recordar, cualquier objeto de una clase que implemente una interfaz en particular pasara el test IS-A (instanceof) para esta interfaz. Por ejemplo, if Box implementa Foldable, lo siguiente seria legal: 4.9. Asignaciones de referencias de array para Arrays Multidimensionales Cuando asignas un array a una referencia array previamente declarada, el array que estas asignando debe tener la misma dimensión que la referencia a la que la estas asignando. Por ejemplo, un array bidimensional de arrays de enteros no puede ser asignado a una referencia de array unidimensional de tipo entero.

Prestar atención a las asignaciones de arrays que tengan diferentes dimensiones. Es posible que, por ejemplo, se pregunte si es legal una asignar una array de enteros al primer elemento en un array de arrays de enteros, como podemos ver a continuación: La siguiente imagen nos muestra ejemplos de asignaciones legales e ilegales de referencia a un array: 4.10. Bloques de inicialización Los bloques de inicialización se ejecutan cuando la clase es cargada por primera vez (un bloque de inicialización estático) o cuando se crea una instancia. Ejemplo: Un bloque de inicialización estático se ejecuta una vez, cuando la clase es cargada por primera vez. Una instancia ejecuta el bloque de inicialización una vez,

cada vez que una nueva instancia es creada. En un constructor el bloque de código de inicialización se ejecuta inmediatamente después de la llamada al constructor super(). Puedes tener muchos bloques de inicialización en una clase. A diferencia de los métodos o los constructores, el orden en que aparecen los bloques de inicialización en una clase. Si hay más de un bloque de inicialización se ejecutara en el orden de aparición en el fichero de la clase. Ejemplo: Para saber la salida debemos recordar las reglas:  Los Bloques de inicialización se ejecutan en el orden en el que aparecen.  Los bloques de inicialización estáticos se ejecutan una vez, cuando la clase es cargada por primera vez.  Los bloques de inicialización de instancia se ejecutan cada vez que se crea una instancia.  Los bloques de inicialización de instancia se ejecutan después de la llamada al constructor super(). Teniendo las reglas 1st static init 2nd static init 1st instance init 2nd instance init no-arg const 1st instance init 2nd instance init 1-arg const en cuenta, la salida siguiente tendría sentido. Como podemos ver los bloques de inicialización de instancia se ejecutaron dos veces cada uno. Los bloques de inicialización de instancia a menudo son usados para poner el código que queremos que todos los constructores de una clase compartan. De esta forma el código no tiene que ser duplicado a través de los constructores. Un error en tu bloque de inicialización estático, la JVM puede lanzar una ExceptionInIninitalizationError. Ejemplo:

Produce Exception Caused at in by: la siguiente salida: thread "main" java.lang.ExceptionInInitializerError java.lang.ArrayIndexOutOfBoundsException: 4 InitError.<clinit>(InitError.java:3) 5. Objetivo de Certificación 3.1 - Usando clases de envoltura y Boxing 3.1 Desarrollar código que use las clases de envoltura de primitivos (tales como Boolean, Character, Double, Integer, etc), y/o autoboxing & unboxing. Discutir las diferencias entre las clases String, StringBuilder y StringBuffer. 5.1. Descripción general de clases de envoltura Hay una clase de envoltura para cada primitivo en Java. Por ejemplo, la clase de envoltura para int es Integer, la clase Float es de float y así todas. A excepción de int que es Integer y char que es Character. La siguiente tabla muestra la lista de clases de envoltura en la API de Java. Clase de Argumentos boolean or Primitivo boolean Boolean envoltura Constructor String byte Byte byte or String char Character char double Double double or String float Float float, double or String int Integer int or String long Long long or String short Short short or String 5.2. Creando objetos de envoltura Para el examen necesitas entender los tres enfoques más comunes para la creación de objetos de envoltura. Algunos enfoques toman un String en representación de un primitivo como argumento. Estos que toman un String lanzan NumberFormatException si el String proporcionado no puede ser parseado al apropiado primitivo. Por ejemplo, "two" no puede ser parseado a "2". Los objetos de envoltura son inmutables. Una vez que hayan obtenido un valor es imposible modificarlo.

5.3. Los constructores de envoltura Todas las clases de envoltura excepto Character proporcionan dos constructores: un que toma un valor primitivo del tipo que está siendo construido y otro que toma un String en representación del tipo que está siendo construido, Por ejemplo: La clase Character proporciona solo un constructor que toma como argumento un char, por ejemplo: El constructor de la clase de envoltura Boolean toma un valor booleano "true" o "false" o un String case-insensitive con el valor "true" o "false". Antes de Java 5, un objeto booleano no podía ser usado como expresión en un test booleano, por ejemplo. A partir de Java 5, un objeto Boolean puede ser usado en un test booleano, ya que el compilador automáticamente convertirse el Boolean a boolean. 5.4. Los métodos valueOf() Los dos métodos estáticos valueOf() proporcionados en la mayoría de clases de envoltura dan otro enfoque para la creación de objetos de envoltura. Ambos métodos toman un String en representación del apropiado tipo de primitivo como primer argumento, el segundo método toma un argumento adicional, int radix, que indica en que base se representado el primer argumento (por ejemplo binario, octal o decimal), veamos un ejemplo a continuación: 5.5. Usando utilidades de conversión en clases de envoltura Los siguientes métodos son los más usados comúnmente y son los que probablemente más veas en el examen.  xxxValue() Cuando necesitas convertir el valor numérico de una clase envoltura a un tipo primitivo use uno de los muchos métodos xxxValue(). Todos los métodos de esta familia no llevan argumentos. Hay 36 métodos xxxValue(). Cada una de las seis

clases de envoltura tiene 6 métodos, así que cualquier numérico de una clase de envoltura puede ser convertido a cualquier tipo numérico primitivo, por ejemplo:  parseXxx() y valueOf() Los seis métodos parseXxx() están estrechamente relacionados con los métodos valueOf() que existen en todos los números de las clases de envoltura. Ambos métodos toman un String como argumento, lanzan un NumberFormatException si el argumento String no está bien formado, y puede convertir objetos String de diferentes bases, cuando el subyacente tipo primitivo es cualquiera de los cuatro tipos de enteros. La diferencia entre los métodos es:  parseXxx devuelve el primitivo nombrado.  valueOf() devuelve un nuevo objeto de la clase de envoltura del tipo que invoca al método. Aquí algunos ejemplos de estos métodos en acción: Los próximos ejemplos involucran el uso del argumento radix (en este caso binario):  toString() La clase Object tiene un método toString(). Las otras clases Java heredan de la clase Object, entonces todas las clases tienen un método toString(). El método toString() te permite obtener una representación significativa de un objeto. Ejemplo:

Todas las clases de envolturas numéricas proporcionan un método sobrecargado toString() que toma un numérico primitivo del tipo apropiado (Doubel.toString() toma un double, Long.toString() toma un long, y así sucesivamente) y devuelve un String: Integer y Long proporcionan un tercer método toString(). Es estático, su primer argumento es el primitivo y su segundo argumento es la base. La base le dice al método que tome el primer argumento y lo convierta a la base proporcionada (la base por defecto es 10), entonces devuelve el resultado como un String, por ejemplo:  toXxxString()(Binario, Hexadecimal, Octal) Las clases de envoltura Integer y Long te permiten convertir un número en base 10 a otras bases. Estos métodos de conversión, toXxxString(), toman un int o long, y devuelven una representación del número convertido, por ejemplo: La siguiente tabla es examen. ~Método (s->static, n>NFE exception byteValue doubleValue floatValue intValue longValue shortValue parseXxx s,n parseXxx (base) s,n valueOf s,n valueOf (base) s,n toString toString(primitivo) s toString(primitivo, base) s la mejor manera para prepararse esta sección para el ~Boolean ~Byte Character Double Float Integer long Short s x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x

En resumen: primitivo xxxValue() - Convierte una clase de envoltura en un primitivo primitivo parseXxx(String) - Convierte un String a un primitivo Clase Envoltura valueOf(String) - Convierte un String a una clase de envoltura  Autoboxing Es una nueva caracteristica de Java 5 conocida como: autoboxing, auto-unboxing, boxing y unboxing. Utilizaremos los términos boxing y unboxing. Boxing y unboxing hacen uso de las clases de envoltura más convenientemente. Antiguamente en Java, antes de Java 5, tú debías hacer lo siguiente: Ahora podemos decir lo siguiente, para obtener la misma funcionalidad: Ambos ejemplos producen la misma salida: y = 568 Es seguro, se ve como se cambia el valor de y de 567 a 568. lo que sucede es que un segundo objeto de clase de envoltura se creó y su valor fue puesto a 568. Vamos a probar lo siguiente: El true 567 false código anterior produce la salida: 568 Así que cuando el compilador llega a la línea y++, tiene que sustituirlo por algo como esto:  Boxing, == y equals() El método equals() determina si dos instancias de una clase dada son equivalentes de manera significativa. Ejemplo :

Produce different objects meaningfully Este same meaningfully la siguiente salida: equal ejemplo produce la salida: object equal Dos instancias de la siguiente lista de objetos de clase de envoltura siempre serán iguales cuando sus valores primitivos sean los mismos:  Boolean  Byte  Character from u0000 to u007f (7f is 127 in decimal)  Short and Integer from -128 to 127 NOTA: Cuando usamos == para comparar un primitivo a una clase de envoltura, la clase de envoltura será unwraped y la comparación será primitivo a primitivo. 5.6. Donde puede ser usado Boxing El siguiente código nos muestra una forma legal de usar boxing: 6. Objetivo de Certificación 1.5 y 5.4 - Sobrecarga 1.5 Desarrollar código que declare métodos estáticos y no estáticos y usar para los métodos nombres que se ajusten al estándar de nombres de JavaBeans. Desarrollar código que declare y use una lista de argumentos variables. Dado un

código de ejemplo, determinar si un método esta correctamente sobrescribiendo o sobrecargando a otro método e identificar valores legales de devolución (return, incluyendo covariantes de return) para el método. 5.4 Dado un escenario, desarrollar código que declare y/o invoque métodos sobrescritos y sobrecargados y código que declare y/o invoque constructores de la superclase, sobrescritos o sobrecargados. 6.1. Sobrecarga - Método concordancia Tres factores que pueden hacer la sobrecarga un poco complicada.  Ampliar (Widening)  Autoboxing  Var-args Cuando una clase tiene métodos sobrecargados, uno de los trabajos del compilador es determinar cual método usar cada vez que encuentre una invocación al método sobrecargado: El int código producirá int la salida long siguiente: double Las llamadas que usan byte y short como argumentos son implícitamente ampliadas (widened) para encajar con la versión del método go() que toma un entero. Por supuesto, la llamada que usa el argumento long usa la versión de go() que toma un long. Y finalmente, la llamada que usa float es encajada con el método que tomaba double. En todos los casos, cuando no se encuentra una exacta conexión, la JVM usa el método con el argumento menor que sea más amplio que el parámetro. 6.2. Sobrecarga - Boxing y Var-args Ahora tomaremos nuestro último ejemplo y le añadiremos boxing:

Como hemos visto anteriormente, si la única versión del método go() fuese una que toma un Integer, entonces La capacidad de boxing de Java5 permitiría la invocación de go(). Del mismo modo, si solo existiese la versión long el compilador lo usaría para hacer la invocación. El compilador elige ampliar antes que realizar boxing, así que la salida sería: long Intenta predecir la salida del siguiente código: Como probablemente adivinaste, la salida es: int, int Ya que, una vez más, aunque cada invocación requiera algún orden de conversión, el compilador elegirá el estilo antiguo antes de elegir el nuevo. Hasta la fecha hemos visto que:  Ampliación (widening) se antepone a boxing.  Ampliación (widening) se antepone a var-args. A continuación veremos quién se antepone a quien, si el boxing a var-args o viceversa: La salida será: Byte, Byte

6.3. Ampliación (widening) de variables de referencia Hemos visto que es legal ampliar un tipo primitivo. Vamos a pensar de nuevo en la asignación polimórfica para ver si se puede hacer ampliación de una variable de referencia y si es así que significaría. En el mismo sentido, una invocación debe ser: El método go() necesita un Animal y Dog3 IS-A Animal. Así que, en este caso, el compilador ampliara la referencia Dog3 a una Animal y la invocación ir bien. La clave aquí es que la ampliación depende de la herencia, en otras palabras el test IS-A. Debido a esto, no es legal ampliar de una clase de envoltura a otra. Por ejemplo, no es correcto decir que Short IS-A Integer 6.4. Sobrecarga combinando Widening y Boxing En este caso el compilador tendrá que ampliar y entonces hacer autobox al parámetro. Esto ya es mucho WidenAndBox.java:6: go(java.lang.Long) applied to para el in WidenAndBox compilador: cannot be (byte) Es posible para el compilador realizar una operación boxing seguida por una operación de ampliación para conseguir encajar una invocación a un método.

Esto compila y produce la salida: 5. Lo siguiente es lo que sucede cuando el compilador llega a la línea que invoca al método go().  Al byte b se le realiza una operación de boxing a Byte.  La referencia Byte se amplía a Object (Byte extiende de Object).  El método go()obtiene una referencia Object que actualmente se refiere a un Byte.  El método go() hace un casting de la referencia Object a una referencia Byte (recordar, nunca hay un objeto Object solo un objeto de tipo Byte).  El método go() pinta el valor del Byte. 6.5. Sobrecarga en combinación con var-args Ejemplo: Esto compila y produce: long... Integer... Las reglas para sobrecargar método usando ampliación, boxing y var-args  Ampliación de primitivos usa el método con el tamaño más pequeño de argumento posible.  Usar individualmente, boxing y var-args es compatible con las sobrecargas.  No se puede ampliar de una clase de envoltura a otra (IS-A falla).  No puedes hacer una ampliación y después box (un int no puede volver a Long).

  Si puedes hacer una operación de box y después una ampliación (un int puede volver a Object, vía Integer). Puedes combinar var-args con ampliación y boxing. Hay más aspectos de sobrecarga, pero lo veremos con mayor profundidad en el capítulo 7. 7. Objetivo de Certificación 7.4 - Garbage Collection 7.1 Dado un código de ejemplo, reconocer los puntos en los cuales un objeto es elegido para garbage collection y determinar que es lo que está garantizado por el sistema garbage collection. Reconocer las características de System.gc y finalización. 7.2. Descripción del garbage collector de Java La memoria Heap es la parte de la memoria donde se almacenan los objetos Java vivos y es la única parte de la memoria que está implicada en el proceso de garbage collection. La función de garbage collector gira en torno a asegurar que la Heap tenga suficiente espacio libre. La función de garbage collector es a eliminar cualquier objeto que no es accesible para el programa Java que este en ejecución. 7.3. Cuando se ejecuta el garbage collector El garbage collector está bajo el control de la JVM. La JVM decide cuando ejecutar el garbage collector. Desde dentro de tu programa puedes pedir a la JVM que ejecute el garbage collector, pero no hay garantías de que la JVM lo vaya a cumplir. La JVM lo ejecutara normalmente cuando vea que la memoria tiene una baja ejecución. 7.4. Escribir código que marque explícitamente objetos elegibles para Collection Vamos a mostrar cómo hacer objetos elegibles para garbage collection usando código. También examinaremos la forma de intentar forzar garbage collection si es necesario y cómo podemos realizar limpieza adicional en objetos antes de ser eliminados de la memoria.  Anulando una referencia La primera forma de eliminar una referencia a un objeto es poniéndole a la variable de referencia que se refiere al objeto null. Fíjate en el siguiente código:

El objeto StringBuffer con el valor Hello es asignado a la variable de referencia sb en la tercera línea. Para hacer al objeto elegible por GC, pondremos la variable de referencia a null, lo cual elimina la única referencia que existía al objeto StringBuffer. Des la línea 6 el objeto ya es elegible para GC.  Reasignando una variable de referencia Tambien podemos hacer que la variable de referencia de un objeto pase a referirse a otro objeto. Observemos el siguiente código: Los objetos que son creados dentro de los métodos también necesitan ser considerados. Cuando un método es invocado, cualquier variable local creada existe solo durante la duración del método. Una vez que el método haya terminado, los objetos creados en el método son elegibles para GC. Hay una excepción obvia, sin embargo. Si un objeto es devuelto desde el método, su referencia debe ser asignada a una variable de referencia en el método que lo llamo, por lo tanto no será elegible para GC. Observemos el siguiente código:

En el ejemplo anterior, creamos un método llamado getDate() que devolvía un objeto Date. Este método crea dos objetos: un Date y un StringBuffer conteniendo la información de la fecha. Desde que el método devuelve el objeto Date, no será elegible para GC incluso después de que el método se haya completado. El objeto StringBuffer será elegible, incluso aunque le indicásemos explícitamente a la variable now el valor null.  Aislando una referencia Hay otra manera de hacer a los objetos elegibles para GC incluso teniendo aún referencias validas. Examinemos el siguiente código: Los tres objetos Island tienen variables de instancia refiriéndose entres sí, pero sus vínculos son el mundo exterior son nulos. Estos tres objetos son elegibles para GC.  Forzando Garbage Collection Las rutinas de Garbage Collection que Java proporciona son miembros de la clase Runtime. La clase Runtime es una clase especial que tiene un solo objeto (singleton) para cada programa principal. El objeto Runtime proporciona un

mecanismo para comunicarse directamente con la JVM. Para obtener la instancia de Runtime, tu puedes usar el método Runtime.getRuntime(), el cual devuelve el singleton. Una vez que tengas el singleton puedes invocar al garbage collector usando el método gc(). Alternativamente, puedes llamar el mismo método en la clase System, que tienen métodos estáticos que pueden hacer el trabajo de obtener el singleton por ti. La manera más fácil de preguntar al GC es: System.gc(); Teóricamente, después de llamar a System.gc(), tendremos la mayor cantidad de memoria libre posible. Decimos teóricamente porque esta rutina no siempre trabaja de esta forma. Primero, tu JVM podrá no tener implementado esta rutina. Segundo, otro hilo podría ocupar gran cantidad de memoria después de haber lanzado el GC. El siguiente ejemplo nos permite ver la cantidad de espacio total que tiene de memoria la JVM disponible y cuanto espacio libre tiene. Si entonces creamos 10000 objetos Date. Después de esto, nos dirá cuanta memoria nos queda y entonces llamaremos al garbage collector. El resultado final de la memoria libre nos indicara si se ha ejecutado el GC. Veamos el código: Ahora Total Before After After ejecutemos el programa y veamos JVM memory: Memory = Memory = GC Memory = su salida: 1048568 703008 458048 818272// La JVM decidió hacer al final el GC de los objetos elegibles. La única cosa que puedes garantizar es que si se está ejecutando la memoria muy lenta, el GC se ejecutara antes de lanzar un OutOfMemoryException

7.6. Limpiando antes de Garbage Collector (método finalize()) Java proporciona un mecanismo para ejecutar algún código justo antes de que el objeto sea eliminado por el GC. Este código está localizado en un método llamado finalize() que todas las clases heredan de la clase Object. Cualquier código que tu pongas en el método finalize() sobrescrito no se garantiza su ejecución. Por lo tanto no pongas código esencial en el método finalize. De hecho, recomendamos que por lo general no se sobrescribe el método finalize(). Guía para el Examen 3.1 Presta una atención especial a los errores en bloques de código. Podrías encontrártelos en bucles como switch, try-catch, for, do y while. Guía para el Examen 3.2 Automático es otro término para las variables locales. No significa que a una variable automática se le asigne automáticamente un valor. Lo verdadero seria lo contrario. Una variable automática debe tener asignada un valor en el código si no el compilador se quejara. Guía para el Examen 3.3 Piense cuantos objetos habrá en la memoria heap después de ejecutar una sentencia o bloque de código. En el examen esperaran que tu lo sepas, por ejemplo en el código que hemos visto anteriormente debemos saber que solo se genera un objeto. El objeto único referenciado por threads contendrá cinco variables de referencia Thread, pero no cinco objetos Thread que tienen que ser creados o asignados a estas referencias. Guía para el Examen 3.4 Tu puedes ver las palabras "construir", "crear" e "instanciar" utilizadas indistintamente. Todas significan, "Un objeto es construido en la memoria heap." Esto también implica que el constructor de objetos se ejecute, como el resultado de crear/construir/instanciar. Se puede decir con certeza, por ejemplo, que cualquier código que use la palabra "new" causara la ejecución del constructor de la clase y de todos los constructores de la superclase. Guía para el Examen 3.5 Busque código que intente acceder fuera del rango de un array. Por ejemplo, si un array tiene tres elementos, intentando acceder al elemento [3] provocara una excepción ArrayIndexOutOfBoundsException, porque en un array de tres elementos, el indice de valores legal seria 0,1 y 2. También debes de estar atento al uso de un número negativo como indice de un array. Los siguientes ejemplos son accesos legales e ilegales. Asegúrate de reconocer que esto provoca excepciones en tiempo de ejecución y no errores de compilación. Casi todas las preguntas de un examen ponen como opción posible las respuestas "error en tiempo de ejecución" y "error de compilación".

Esto puede ser difícil de encontrar en un bucle complejo. Pero hay es donde mas problemas de indices de array se producen en las preguntas del examen. Guía para el Examen 3.6 Recordar que no especificas un tamaño cuando usas la sintaxis de creación anonima de array- El tamaño es derivado del número de comas (,) entre las llaves. Esta atento a preguntas del examen que pongan algo parecido a lo siguiente. Guía para el Examen 3.7 Las asignaciones de un array de una subclase, no pueden ser asignados a un array cuyo tipo es la superclase. Por ejemplo, siguiendo con el ejemplo de Car y Subaru. Un array de Car no puede ser asignado a un array de Subaru. Un Car no necesariamente tiene que ser Subaru. Recuerda que el test IS-A se puede hacer usando el operador instanceof. Guía para el Examen 3.8 Por convenio, los bloques de inicialización normalmente aparecen cerca de la parte de arriba del fichero de una clase, alrededor de los constructores. A menudo, this is the SCJP exam we're talking about. Don't be surprised if you find an init block tucked in between a couple of methods, looking for all the world like a compiler error waiting to happen! Guía para el Examen 3.9 Recordar, variables de referencia cuyo tipo es una clase de envoltura pueden ser null. Esto significa que tienes que estar atento al código que parece estar haciendo operaciones primitivas seguras, pero que podrían lanzar un NullPointerException.

Este código compila bien, pero la JVM lanza un NullPointerException cuando intente invocar doStuff(x), porque x no esta referenciado a ningún objeto Integer, así que no hay valor para realizar unbox. Guía para el Examen 3.10 Es tentador pensar que podriamos ser capaces de ampliaruna clase de envoltura Integer a otra Long, pero como veremos a continuación el siguiente código no compilara: Recuerda, ninguna de las clases de envoltura sera ampliada de una a otra. Bytes no se puede ampliar a Shorts, Shorts no se puede ampliar a Longs ...etc.

Add a comment

Related presentations

Related pages

Java SE 6 Programmer Certified Professional | Oracle ...

Purchase exam voucher from Oracle University; Register for exam at PearsonVue or locate a test center near you : Exam Preparation; Exam Topics; More ...
Read more

Oracle Certified Professional, Java SE 6 Programmer - Acclaim

An Oracle Certified Professional, Java SE 6 Programmer has experience using the Java programming language, understands the basic syntax and structure of ...
Read more

NEW CERTIFICATION: Oracle Certified Professional (OCP ...

NEW CERTIFICATION: Oracle Certified Professional ... new "Oracle Certified Professional, Java SE 7 Programmer ... Oracle Certified Master, Java SE 6 ...
Read more

Oracle Certified Professional, Java SE 6 Programmer ...

Oracle Certified Professional, Java SE 6 Programmer ... Oracle Certified Professional, Java SE 6 Programmer Preparation ... • Topic 3 API Contents ...
Read more

NO_DATA_FOUND - education.oracle.com

Java Certified Professional ... Certified Java Programmer Certified Java Developer ... Oracle Certified Associates, ...
Read more

Oracle Certification Program - Wikipedia

The Oracle Certification Program certifies ... Oracle Certified Professional, Java SE 6 Programmer: ... Oracle Certified Professional, Java SE 6 ...
Read more

What is SCJP 6 - Java Certification Preparation and Training

... for Oracle Certified Professional, Java SE 6 ... What is SCJP 6 ? ... Oracle Certified Professional, Java SE 6 Programmer Certification ...
Read more

Weiterbildung OCPJP - Oracle Certified Professional, Java

... Oracle Certified Professional, Java SE ... Oracle Certified Professional, Java SE 7 Programmer ... Developer und der Oracle Certified Expert, Java EE 6 ...
Read more

Guía Rápida Java Programmer 6 | Preparando SCJP

... Oracle Certified Professional, Java SE 6 Programmer ... 3. API Contents 4 ... me interesa el certificado “Oracle Certified Professional, Java SE 6 ...
Read more

Zertifizierungs-News - Oracle

Die Zertifizierung Oracle Certified Professional (OCP) Java SE 7 geht sehr viel weiter ... There are well over 1.3 million people worldwide certified on ...
Read more