0-02 DECLARACIÓN DE VARIABLES.
Una variable es un elemento en el que podemos almacenar valores que pueden cambiar a lo largo del tiempo. Son primitivas y referenciadas.
Nombres válidos de variables: no empezar NUNCA con número ni ser una palabra reservada. Símbolos permitidos $ _.
Variables globales, también llamadas atributos, campos de la clase, variables miembro de la clase o variables de instancia.
Variables locales (definidas dentro de un método, constructor o bloque).
Variables finales (constantes).
Inicialización por defecto de las globales. Necesidad de inicializar las locales antes de usarlas.
Ámbito de existencia globales y locales. Globales = toda la clase. Locales = sólo dentro del método (si mismo nombre que global, usar this).
Ambigüedad cuando una variable local y global tiene el mismo nombre. Solución mediante el operador this. Se admiten tipos distintos para cada una.
Variables estáticas (static) o de tipo compartido (la misma para todos). No requieren instanciación. Viven en la clase, no en la instancia.
Convenio de nombres para variables finales y no finales. El nombre de las finales se pone todo en mayúsculas.
Se puede usar abstract para declarar una variable local, pero NUNCA GLOBAL (aunque no tiene ninguna utilidad, al menos en apariencia).
0-03 VARIABLES DE TIPO PRIMITIVO.
boolean(1 bit)
byte(8), short(16), char(16), int(32), long(64 .. l, L) … los char no tienen signo (0 … 65535).
float(32 .. f, F), double(64 .. d, D) ... En cuanto pongamos el pto decimal, ya es double. Usar f o F para indicar Float
float f = 3.0F;
Inicialización (cuando es variable global):
boolean --> false. No es un número, no puede mezclarse con el resto de primitivos.
byte --> 0
short --> 0
char --> \u0000 (unicode 16 bits sin signo). También es un número.
int --> 0
float --> 0.0
double --> 0.0
Autopromoción a int (Upgrading --- pasar de un tipo inferior a uno superior ... byte, short, char int).
Los float no promocionan a double al sumarlos entre sí, pero algo como 3.0 es double y no float. Usaremos los suficios f y F para indicar float (3.0F)
Mezcla de tipos numéricos. Obligatoriedad de almacenar el resultado en un tipo con tamaño suficientemente grande --> int o el mayor de todos ellos.
Notación hexadecimal con 0x ... 0x1, 0XA, 0xFFF
Notación octal con 0numero (0 ... 7). ... 01, 07, 010, 0123
*** Los tipos referenciados, se inicializan a null. Una “cadena de texto” es la clase java.lang.String.
ARRAYS / MATRICES.
Es un tipo de objeto Java ... Tamaño fijo, no crece dinámicamente y no puede contener distintos tipos de elementos, pero sí subtipos de uno dado.
Elementos empiezan en posición 0 y se inicializan al valor por defecto del tipo correspondiente (porque un array es un objeto de una clase).
Propiedad .lenght (no es método como en los String).
Excepción no comprobada ArrayIndexOutOfBoundsException.
Los que contienen objetos, en realidad sólo almacenan la referencia, no el objeto en sí (todos, incluído el propio array, están en Heap de memoria).
Unidimensionales (un array de elementos primitivos-referenciados):
int[] datos = new int[3]; … relleno por ejemplo con un bucle for.
int[] datos = {1,2,3}; … en la parte de la declaración (izquierda), nunca se da la dimensión.
int[] datos = new int[] {1,2,3}; … si se indican los elementos, no se puede indicar la dimensión (cálculo automático del sistema).
Multidimensionales ( un array de arrays, así, la segunda dimensión es un xxx[] ):
int[][] matriz = new int[2][]; ... El valor de la segunda dimensión es opcional, en la declaración no se tiene en cuenta.
int[][] matriz = { {1,1}, {2,2}, {3,3} }; ... y el segundo recorrería cada uno de los elementos de dichos arrays obtenidos (columnas).
int[][] matriz = new int[][] { {1,1}, {2,2}, {3,3} };
int[][] matriz = { new int[]{1,1}, new int[]{2,2}, new int[]{3,3,} };
int[][] matriz = new int[2][]; … Podemos dar dimensión al primer corchete sin el segundo, pero no al revés (puede ser irregular).
Longitud – propiedad: .lenght ... en el caso de multidimensión, nos la la longitud de la primera dimensión (número filas).
Método especial de copia: .clone()
Otro forma de copiar: System.arraycopy(origen, pos_ini_origen, destino, pos_ini_destino, cuantos_elementos)
No es habitual el uso de arrays de más de 2 dimensiones. En cualquier caso, cada dimensión esta compuesta por 1 array, de forma que en 2D, tenemos
un array principal que contiene en cada una de sus posiciones a otros arrays ... y cada uno de ellos a su vez a otros arrays en el caso de 3D y así
sucesivamente.
Para poder utilizar la referencia de un array con el objeto de manejar a otro, AMBOS DEBEN TENER EXACTAMENTE LA MISMA DIMENSIÓN.
No podemos utilizar una referencia de tipo 2D para manejar uno de dimensión 1D ya que no son compatibles entre si.
2D --> ARRAY_CONTENEDOR [ SUB_ARRAY_1, SUB_ARRAY2, SUB_ARRAY_3 ] --> una matriz de arrays == filas de arrays (válido irregular).
1er elemento = SUB_ARRAY_1 2do elemento = SUB_ARRAY_2 3er elemento = SUB_ARRAY_3
Así, para poder obtener un elemento en concreto con 2D, deberemos dar las coordenadas de cada dimensión [][].
Si sólo damos la primera, obtendremos el array correspondiente a dicha coordenada.
CASOS ESPECIALES EN LA DECLARACIÓN Y ASIGNACIÓN DE LOS ARRAYS:
Se puede manejar un array de subtipos con un array de tipo o supertipo de este:
Animal[] animales = new Gato[3]; // CORRECTO (los arrays son Type-Safe).
//Se guardan los elementos como de tipo Animal, no como Gato, ya que la referencia del array es de tipo Animal.
Una colección con género no admite polimorfismo en la declaración del tipo:
ArrayList<Animal> misAnimales = new ArrayList<Gato>(); // ERROR COMPILADOR.
ArrayList<Object> misAnimales = new ArrayList<Gato>(); // ERROR COMPILADOR.
Un array de tipos primitivos no puede manejar un array de otro tipo primitivo que no sea el suyo (ni siquiera aunque sea un tipo inferior en rango):
int[] numeros = new byte[3]; // ERROR COMPILADOR.
Un array de tipos Wrapper no puede manejar un array de primitivos, ni siquiera del tipo primitivo que le corresponde:
Integer[] wrapper = new int[3]; // ERROR COMPILADOR.
Podemos ordenar los elementos de un array (si estos son ordenables) mediante Arrays.sort(el_array) ... los cambios quedan sobre el array original.
CONTROL DE FLUJO – SENTENCIAS Y BLOQUES CONDICIONALES.
BUCLES(Loops).
CONDICIONALES:
if condicional simple.
if else condicional doble
if else if else condicional múltiple
No podemos declarar variables en los paréntesis del if, pero sí usar las externas a éste, asignándolas un valor directamente o
mediante la invocación a un método. Dichas variables no pueden volverse a declarar dentro de las llaves del if.
Se pueden declarar variables dentro de las llaves del if, pero su visibilidad quedará limitada a dichas llaves (no se verán fuera).
El resultado final de lo encerrado entre paréntesis, ha de ser siempre un booleano.
Una vez encontrado un condicional válido (que devuelva true), no se evalúa el resto de dicho grupo (if-else if-else).
La declaración de variables locales a un método, constructor o bloque, es siempre en orden de arriba a abajo, a diferencia de las
globales que pueden declararse al final de la clase, a continuación de los métodos, sin que ésto afecte a su visibilidad.
bloque switch:
switch (condición) {
case valor1:
líneas a ejecutar;
break;
default:
líneas a ejecutar;
}
Funcionamiento de un bloque SWITCH:
Válido sólo para los tipos primitivos byte, short, char, int y los Wrappers de éstos gracias al autounboxing.
Válido para tipos enumerados.
Vigilar el FALL-THROUGH o caída libre y dónde ponemos el default.
Claúsulas case y default son opcionales.
No podemos repetir 2 o más condiciones case.
El único operador que se permite es el de igualdad (==), por lo que no podemos utilizar los operadores !, <, >, <=, >=. Así, no podremos comprobar rangos.
Entra por el primer case válido y sigue hacia abajo hasta el primer break. Por el default entraremos si no hay ningún case válido (no importa posición) y a partir
de ahí, hacia abajo hasta el primer break, atravesando todos aquellos case que pudiera encontrar en su camino (no evalúa su condición). Es por ésto que lo habitual
es ubicar el default el último, aunque también sería válido si le añadimos a continuación un break a ese default colocado en una posición que no es la final.
BUCLES (Loops): ... vigilar los bucles infinitos (desbordamiento de pila).
bucle for tradicional:
for (incialización; condición; operaciones) {} ... son opcionales: for(;😉.
... inicialización válida: for(int x=3, y=7; ; ) . Sólo se permite 1 tipo.
... se permiten múltiples operaciones separadas por comas (,).
... da lo mismo usar ++contador que contador++ en operaciones.
... inicializa -> comprueba -> { ejecuta código | sal } -> comprueba ... etc.
bucle for-each: ... no es válido ni para Enumeration ni para Iterator.
for (tipo variable : colección/array) {}
while (condición) {} ... 0 o infinitas veces.
do {} while (condición); ... 1 o infinitas veces … pero por lo menos 1. No olvidar el ; del final.
SALTOS:
break; ... rompe el bucle por completo.
continue; ... se salta un determinado paso del bucle, no todo.
SALTOS CON ETIQUETA (útil cuando tenemos anidamiento de bloques y queremos poder elegir romper los internos o los externos):
salto:
break salto;
continue salto;
Como esto último es más bien un esquema para revisar cuando lo tengas claro te dejo unos videos tutoriales muy ilustrativos.
Variables
[youtube]http://youtu.be/dnFaXbSToQY**