Resumen Stack y Heap, Literales, Ámbito de variables, Asignaciones básicas, Uso de una variable o elemento de un Array, Arrays, Paso de variables en un método, Bloques de Inicialización, Wrapper, Boxing, Sobrecarga Avanzada, GC en Java

En esta entrada vamos a tener un breve resumen sobre lo mas importante que hemos dado sobre: Stack y Heap, Literales y Casting de Primitives, Ámbito de variables. Asignaciones básicas, Uso de una variable o un Elemento de un Array que está sin inicializar y sin asignar, Paso de variables en un método, Declaración de un Array, construcción e Inicialización, Bloques de Inicialización, Wrappers, Boxing, Sobrecarga Avanzada, Garbage Collector.


  • Stak y Heap

    • Las variables locales (o variables de método) residen en el stack.
    • Los objetos y sus variables de instancia residen en el heap.
  • Literales y Casting de Primitivos

    • Los literales enteros pueden ser decimales, octales o hexadecimales.
    • Los literales para longs terminan en L o l.
    • Los literales Float terminan con F o f, y los literales double terminan con el dígito D o d.
    • Los literales boolean son true o false.
    • Los literales para chars son un caracter dentro de comillas simples: ‘d’.
  • Ámbito de variables

    • El ámbito de una variable se refiere al tiempo de vida de una variable.
    • Hay 4 ámbitos básicos:
      • Variables Static viven básicamente tanto como la clase viva.
      • Variables de instancia viven tanto como su objeto viva.
      • Variables locales viven tanto como el método esté en el stack, sin embargo, si el método invoca otro método, no estará disponible temporalmente.
      • Las variables de bloque viven hasta que el bloque se completa.
  • Asignaciones Básicas:

    • Los literales enteros son implícitamente int.
    • Las expresiones enteras siempre resultan en un resultado del tamaño de un int, nunca menor.
    • Los números floating-point son implícitamente doubles (64 bits).
    • Estrechar un primitivo trunca los bits de orden superior.
    • Las asignaciones de composicion (+=, +=), realizan un cast automático.
    • Una variable de referencia almacena los bits que son usados para referirse a un objeto.
    • Las variables de referencia pueden referir a subclases del tipo declarado pero no a superclases.
    • Cuando se crea un nuevo objeto, ocurren 3 cosas:
      • Se crea una variable de referencia.
      • Se crea el objeto.
      • Se asigna el objeto a la variable de referencia.
  • Usar una variable o un Elemento de un Array que no ha sido inicializado ni asignado:

    • Cuando un array de objetos es instanciado, los objetos dentro del array no son instanciados automáticamente, pero todas las referencias obtienen el valor por defecto null.
    • Cuando un array de primitivos es instanciado, los elementos obtienen sus valores por defecto.
    • Las variables de instancia son siempre inicializadas con el valor por defecto.
    • Las variables locales o de método nunca obtienen valor por defecto. Si intentamos usar una antes de inicializarla, obtendremos un error de compilador.
  • Pasando variables a métodos

    • Los métodos pueden coger primitivos y/o referencias a objetos como argumentos.
    • Los argumentos de los métodos son siempre copias.
    • Los argumentos de los métodos nunca son objetos actuales.
    • Un argumento primitivo es una copia que no está ligada al primitivo original.
    • Un argumento que es referencia a otra copia es una referencia al objeto original.
    • Ocurre Shadowing cuando 2 variables con diferentes ámbitos de variable comparten el mismo nombre. Esto desemboca en bigs dificiles de encontrar.
  • Declaración de Array, Construcción e Inicialización

    • Los arrays pueden almacenar primitivos u objetos, pero el array por sí mismo es un objeto.
    • Cuando declaramos un array, los corchetes pueden estar a la izquierda o a al derecha del nombre.
    • Nunca será legal incluir el tamaño de un array en la declaración.
    • Se debe incluir el tamaño del array cuando lo construimos (usando new) a no ser que estemos creando un array anónimo.
    • Los elementos de un array de objetos no son automáticamente creados, aunque en un array de elementos primitivos les es dado su valor por defecto.
    • Obtendremos un NullPointerExceptiom si intentamos usar un array de elementos en un array de objetos, si el elemento no se refiere a un objeto real.
    • El primer índice de un array comienza con 0.
    • Un ArrayIndexOutOfBoundsException ocurre si usamos un valor erróneo como índice.
    • Los arrays tienen una variable que nos indica su longitud la cual es la cantidad de elementos que tiene el array.
    • El último índice al que podemos acceder es siempre la longitud del array menos uno.
    • Los arrays multidimensionales son arrays de arrays.
    • Las dimensiones de un array multidimensional pueden ser de diferentes longitudes.
    • Un array de primitivos puede aceptar cualquier valor que pueda ser implícitamente promovido al tipo de array declarado.
    • Un array de objetos puede almacenar cualquier objeto que pase el test IS-A para el tipo declarado del array.
    • Si asignamos un array a una referencia de un array previamente declarada, el array que estamos asignando debe de tener la misma dimensión que el de la referencia al que la estamos asignando.
    • Podemos asignar un array de un tipo a otroa referencia de array previamente declarada de su supertipo.
  • Bloques de Inicialización

    • Los bloques de inicialización static solo se ejecutan uan vez, cuando la clase es por primera vez cargada.
    • Los bloques de inicialización de instancia se ejecutan cada vez que una instancia nueva es creada. Se ejecutan después de todos los super-constructores se hayan ejecutado y antes de los constructores del código se hayan ejecutado.
    • Si existen múltiples bloques de inicialización en una clase, se ejecutan según al regla que hemos visto en el punto anterior, y en el orden en el cual aparecen en el código fuente.
  • Wrappers

    • Las clases Wrapper son correlativas a los tipos primitivos.
    • Los Wrappers tienen 2 funciones:
      • Envolver primitivos de manera que puedan ser tratados como objetos.
      • Proveer métodos de utilidad para primitivos (normalmente conversiones).
    • Las 3 familias de métodos mas importantes son:
      • xxxValue() – No tiene argumentos, retorna un primitive.
      • parseXxx() – String como argumento, retorna un primitivo, lanza NFE.
      • valueOf() – String como argumento, retorna un objeto envuelto, lanza NFE.
    • Los constructores de las Wrapper pueden tener un String o primitive como argumento, excepto para Character, que solo puede tener un char.
    • Radix se refiere a las bases que no sean 10; octal es radix = 8, hex = 16.
  • Boxing

    • El Boxing permite convertir primitivos a wrappers o convertir wrappers en primitivos automáticamente.
    • Usar == con las wrappers creadas a través del boxing es dificil.
  • Sobrecarga Avanzada

    • La ampliación de primitivos usa el método que tenga menor numero de argumentos posibles.
    • Usado individualmente, el boxing y los var-args son compatibles con la sobrecarga.
    • No podemos ampliar de un tipo wrapper a otro (IS-A falla).
    • No podemos ampliar y entonces hacer box.
    • Podemos hacer box y luego ampliar.
    • Podemos combinar var-args con ampliación o boxing.
  • Garbage Collection:

    • En Java, el GC provee una administración de memoria automática.
    • El propósito del GC es eliminar objetos que ya no pueden ser alcanzados.
    • Solo la JVM decide cuando ejecutar el GC, nosotros solo podemos sugerirlo.
    • No podemos saber el algoritmo del GC por seguro.
    • Los objetos deben ser considerados elegibles antes de que puedan ser recogidos por el GC.
    • Un objeto es elegible cuando ningún thread con vida puede alcanzarlo.
    • Para alcanzar un objeto, debemos tener una referencia viva y alcanzable a ese objeto.
    • Una aplicación de Java puede quedarse sin memoria.
    • Una isla de objetos puede ser GCed, incluso si se refieren unas a otras.
    • Se puede requerir un GC con System.gc().
    • La clase Object tiene el método finalize().
    • El método finalize() nos garantiza que se ejecuta una vez y solo una antes de que el GC borre el objeto.
    • El GC no ofrece garantias de que finalize() se ejecute.
    • Podemos hacer que un objeto no sea elegible para el GC desde dentro del finalize().