13
Mar 14

Pildoritas de POO y Java: Conceptos básicos de programación. Sentencias

pildoras poo java
Hoy ponemos punto y final a la parte de Conceptos Básicos de Programación de las Pildoritas de POO y Java, donde veremos la última parte de los algoritmos, las sentencias.

Veremos las sentencias de E/S, las funciones y las sentencias de flujo. Con esto y lo visto en las otras dos pildoritas anteriores, ya tendremos unos conocimientos aceptables de programación para poder afrontar la parte de Programación Orientada a Objetos.

Sentencias

Hasta donde hemos visto hasta ahora, las instrucciones de un algoritmo se ejecutan de forma secuencial, pero a veces necesitamos sólo ejecutar una parte del código o repetir varias veces un conjunto de instrucciones. Además, podemos interactuar con dispositivos de E/S o invocar porciones de código encapsulas por medio de un identificador.

Sentencias de E/S

Las sentencias de entrada y salida son aquellas que interactúan con el resto de dispositivos del ordenador. Por ejemplo, esperar a que el usuario introduzca un valor por consola, o que haga click sobre una determinada porción de la pantalla.

En el caso de Java, la entrada y salida se gestiona a partir de una clase (tipo, hablando de forma burda) que viene por defecto en la Máquina Virtual de Java, la clase System.

// Muestra por pantalla el mensaje pasado por parametro (de tipo String)
System.out.println("OLA K ASE?")

Funciones

Las funciones son módulos independientes de código que se ejecutan solamente cuando se les invoca y que pueden, o no, devolver un valor.

En la Programación teórica los módulos que no devuelven valor son procedimientos, y aquellos que sí lo hacen, se llaman funciones. En Java y otros lenguajes como C no existe tal separación y un procedimiento simplemente es una función que no devuelve valor alguno.

Veamos un ejemplo de una función:

int suma (int op1, int op2) {
	int resultado = op1 + op2;
	return resultado;
}

Y un procedimiento sería simplemente una función que no devuelve nada (void).

void suma2 (int op1, int op2) {
     int resultado = op1 + op2;
     System.out.println("La suma es: " + resultado);
}

* Cuando una sentencia incluye más de una instrucción se utilizan las llaves, {}, para indicar que esa porción de código pertenece a dicha sentencia.

La sentencia return es por sí misma una sentencia de flujo. Podemos indicar la sentencia return en otra parte de la función, lo que cortaría la ejecución de ésta y volvería al código principal.

Para llamar a una función lo haríamos de la siguiente forma:

int a = suma (3, 5);  //a vale 8

Las funciones pueden recibir, o no, parámetros, que irán indicados entre paréntesis y separados por coma. Los parámetros pueden ser de dos tipos, de paso por valor o por referencia.

En el primer caso, se realiza una copia a nivel de función de la variable. Cuando pasamos una variable por referencia, los cambios que realicemos en la función también afectarán a la variable que indicamos en la llamada a la función.

En Java, el paso de los parámetros siempre se realizará por valor.

Sentencias de control de flujo

Las sentencias de control de flujo dirigen el flujo del programa por una parte de código determinada, dependiendo de unas condiciones fijadas.

Hay varios tipos de sentencias de control de flujo: los ifs, los bucles, los capturadores de excepciones y otros muchos más.

if-then-else

La sentencia if-then-else es la sentencia más básica de control de flujo. Indica al compilador o intérprete que debe evaluar una parte del código sólo sí una determinada condición es verdadera. La parte del else es opcional.

Veamos varios ejemplos:

if (a < b) 
     c = 1;
else
     c = 2;

// Si a es menor que b, c valdrá 1, en caso contrario, valdrá 2

También podemos concatenar varios else seguidos de una condición indicada por el if:

if (a==b)
     c  = 0;
else if (a < b)
     c = 1;
else
     c = 2;

Si vamos a evaluar el valor de una variable cualquiera y necesitamos un gran número de bloques else, podemos utilizar la sentencia switch:

int mes;
switch (mes) {
     case 1:  System.out.println("Enero"); break;
     case 2:  System.out.println("Febrero"); break;
     case 3:  System.out.println("Marzo"); break;
     case 4:  System.out.println("Abril"); break;
     case 5:  System.out.println("Mayo"); break;
     case 6:  System.out.println("Junio"); break;
     case 7:  System.out.println("Julio"); break;
     case 8:  System.out.println("Agosto"); break;
     case 9:  System.out.println("Septiembre"); break;
     case 10: System.out.println("Octubre"); break;
     case 11: System.out.println("Noviembre"); break;
     case 12: System.out.println("Diciembre"); break;
     default: System.out.println("Mes incorrecto.");break;
 }

Los break, como veremos luego, también son sentencias de flujo por sí mismas. Lo que hacen las sentencias break es salir de sentencias de flujo, como son los ifs, switch y bucles. Por ejemplo, en este ejemplo utilizamos un break porque de lo contrario se seguirían evaluando el resto de casos del switch.

Bucles

Los bucles se utilizan para ejecutar un conjunto de instrucciones varias veces basándose en una condición determinada que indicará si el flujo debe continuar ejecutando este bloque de instrucciones o si por el contrario deberá salir del bucle y continuar la ejecución del resto del código fuente.

Hay diferentes tipos de bucles, veamos cuales son y en que se diferencian.

while y do-while

Los bucles while y do-while ejecutan un conjunto de instrucciones mientras se cumpla una determinada condición. Estos bucles se suelen utilizar cuando no conocemos el número de repeticiones.

while (expresión) {bloque de instrucciones}

do {bloque de instrucciones} while (expresión)

Se ejecutarán las sentencias incluidas entre las llaves del bloque while mientras la expresión de ésta se cumpla.

int contador;
while (contador > 1) 
     contador--;

do {
     contador--;
} while (contador > 1);

La diferencia entre while y do-while es que el bucle while primero evalúa la expresión y luego ejecuta el bloque de instrucciones, mientras que do-while primero ejecuta la porción de código y después evalúa la expresión. Por tanto, el bucle do-while se ejecutará al menos una vez.

for

El bucle for es el que utilizaremos cuando conozcamos el número de repeticiones. En la mayoría de ocasiones se ven cuando recorremos Listas, Vectores, o cualquier otro tipo de Colecciones.

En Java existen dos tipos de bucle for: el básico, que tiene una sintaxis idéntica a C, y el mejorado, que está especialmente diseñado para recorrer colecciones.

for básico
En el for básico indicaremos una variable y su inicialización, que utilizaremos como contador, la condición de parada, y por último, el incremento que se realizará sobre el contador en cada ejecución del bucle.

Su sintaxis en Java es la que sigue:

for (inicialización ; condición de terminación ; incremento) { 
     bloque de instrucciones 
}

Veamos un ejemplo práctico:

final int INTERACCIONES = 10;

for (int i = 0; i < INTERACCIONES; i++) 
     System.out.println("Interacción número " + i);

for mejorado
En el for mejorado se indicará en primer lugar el elemento del método que se evalúa en ese momento, y tras esto, la colección a evaluar.

int[] array = {2, 4, 6, 8, 10};
int sumatorio = 0;

for (int elemento : array) {
     sumatorio += elemento;
     System.out.println("El elemento evaluado es: " + elemento);
}

Los for mejorados siempre pueden traducirse en for básicos:

int[] array = {2, 4, 6, 8, 10};
int sumatorio = 0;
int elemento = 0;

for (int j = 0; j < array.length; j++) {
     sumatorio += elemento;
     System.out.println("El elemento evaluado es: " + elemento);
}
System.out.println("El sumatorio del array vale: " + sumatorio);

Otras sentencias de flujo

Excepciones
El tratamiento de excepciones es una técnica de programación que permite al programador controlar errores ocasionados durante la ejecución de un programa.

Las excepciones son eventos que interrumpen la ejecución del programa. Por noma general estas excepciones se lanzan cuando ocurre un error en el programa, ya sea por acceder a una variable vacía, leer un fichero que no existe..., y lanzadas por el propio programador.

Además, las excepciones pueden capturarse por medio de bloques try-catch-finally.

En el bloque try se ejecuta el código que se desea “controlar”.

El bloque catch será aquel que se ejecute cuando se lance una de las excepciones a capturar.

Por último, el bloque finally es opcional y se ejecutará SIEMPRE, se capture o no un error.

Hay muchos tipos de error, pero el más genérico es Exception.

try {
     if (metros > LIMITE_MAX)
          throw new Exception("Limite máximo demasiado grande");
     else
          metrosCuadrados = metros * metros;
} catch (Exception e) {
     e.printStackTrace();
}
finally {
     System.out.println("Fin del bloque");
}

Tampoco entraremos mucho en este tema, ya que es un concepto más avanzado de Java que me gustaría explicar en profundidad al final de las pildoritas.

break
El comando break hace que automáticamente el flujo salga del if o el bucle que lo contiene, sin evaluar el resto de código de esa parte.

while(i > 0) {
     if (i == 3) break;
     i--;
}

Si la variable i vale 3 en algún momento, se saldrá del bucle while.

return

Como ya adelantábamos en la parte de funciones, el bloque return también puede redirigir el flujo del programa, ya que puede cortar la ejecución de una función saliendo al código principal.

String devolverMes(int codigo) {
	     switch (codigo) {
	          case 1:  return "Enero";
	          case 2:  return "Febrero";
	          case 3:  return "Marzo";
	          case 4:  return "Abril";
	          case 5:  return "Mayo";
	          case 6:  return "Junio";
	          case 7:  return "Julio";
	          case 8:  return "Agosto";
	          case 9:  return "Septiembre";
	          case 10: return "Octubre";
	          case 11: return "Noviembre";
	          case 12: return "Diciembre";
	          default: return "Mes incorrecto";
	     }
	}

Si los bucles if-then-else o switch contemplan todos los posibles casos, no hará falta tener un return final. De no ser así, habrá que colocar un return al final de la función. De no ser así se mostraría un error en su compilación.

Si queremos cortar la ejecución del código de una función que no devuelve nada (void) utilizaremos la sentencia return sin devolver nada: return;

Bajo mi punto de vista, hay que evitar los break para salir de una sentencias de flujo. Siempre es más controlable y comprensible introducirlo como una propia condición más y jugar con variables locales.

Los return también es mejor utilizarlos sólo al final de la función, y que se lleve una variable del tipo de la función que almacene los valores que queremos devolver.

 

Y ya por fin, terminamos la parte de conceptos básicos. Ahora que tenéis unos conocimientos generales de Java y programación, puedo continuar con el tema principal de este post, la Programación Orientada a Objetos.

Mientras veamos POO también seguiremos viendo más cosas de Java y al final de todo, seguramente dedique alguna pildorita a ver conceptos importantes en Java que no hayan podido ser abarcadas en las restantes pildoritas.

Índice de Pildoritas

Share