|
Control de Flujo |
Anterior | Siguiente |
El control del flujo es la manera que tiene un
lenguaje de programación de provocar que el flujo de la ejecución avance y se ramifique
en función de los cambios de estado de los datos. Java, en este aspecto, no utiliza los
principios de diseño orientado a objetos, sino que las sentencias de control del flujo
del programa se han tomado del C/C++. A continuación se tratan todos los mecanismos que
proporciona Java para conseguir este control y decidir qué partes del código ejecutar.
if( expresión-booleana ) { sentencias; } [else { sentencias; }] Esta construcción provoca que la ejecución atraviese un conjunto de estados booleanos que determinan que se ejecuten distintos fragmentos de código. La cláusula else es opcional. Cada una de las sentencias puede ser una sentencia compuesta y la expresión-booleana podría ser una variable simple declarada como boolean, o una expresión que utilice operadores relacionales para generar el resultado de una comparación. En el ejemplo java405.java, se utilizan varias sentencias if-else para determinar en qué estación del año se encuentra un mes determinado. Cuando se ejecuta el programa, la salida que se obtienes en pantalla es la que indica la estación en la que se encuentra el mes en que se está escribiendo el código de esta aplicación: %java java405 Agosto esta en el verano. switch( expresión ) { case valor1: sentencias; break; case valor2: sentencias; break; [default: sentencias;] } La sentencia switch proporciona una forma limpia de enviar la ejecución a partes diferentes del código en base al valor de una única variable o expresión. La expresión puede devolver cualquier tipo básico, y cada uno de los valores especificados en las sentencias case debe ser de un tipo compatible. En Java no se puede realizar una comprobación contra caracteres como en C++, porque el tipo char en C++ es en realidad un entero de 8 bits, lo que no es cierto en Java. La sentencia switch funciona de la siguiente manera: el valor de la expresión se compara con cada uno de los valores literales de las sentencias case. Si coincide con alguno, se ejecuta el código que sigue a la sentencia case. Si no coincide con ninguno de ellos, entonces se ejecuta la sentencia default (por defecto), que es opcional. Si no hay sentencia default y no coincide con ninguno de los valores, no hace nada. Al igual que en otros lenguajes, cada constante en sentencia case debe ser única. El compilador de Java inspeccionara cada uno de los valores que pueda tomar la expresión en base a las sentencias case que se proporcionen, y creará una tabla eficiente que utiliza para ramificar el control del flujo al case adecuado dependiendo del valor que tome la expresión. Por lo tanto, si se necesita seleccionar entre un gran grupo de valores, una sentencia switch se ejecutará mucho más rápido que la lógica equivalente codificada utilizado sentencias if-else. La palabra clave break se utiliza habitualmente en sentencias switch sin etiqueta, para que la ejecución salte tras el final de la sentencia switch. Si no se pone el break, la ejecución continuará en el siguiente case. Es un error habitual a la hora de programar el olvidar un break; dado que el compilador no avisa de dichas omisiones, es una buena idea poner un comentario en los sitios en los que normalmente se pondría el break, diciendo que la intención es que el case continúe en el siguiente, por convenio este comentario es simplemente, "Continúa". Otra diferencia de Java con C++ respecto a la sentencia switch es que Java soporta sentencias break etiquetadas. Esta característica puede hacer que el entorno de funcionamiento sea muy diferente entre ambos lenguajes cuando hay sentencias switch anidadas. El ejemplo java406.java es el mismo ejemplo que se creó en la sección if-else, reescrito para utilizar switch. for( inicialización; terminación; iteración ) { sentencias; } Un bucle for, normalmente involucra a tres acciones en su ejecución:
La cláusula de inicio y la cláusula de incremento pueden estar compuestas por varias expresiones separadas mediante el operador coma (,), que en estos bucles Java también soporta. for( a=0,b=0; a < 7; a++,b+=2 ) El operador coma garantiza que el operando de su izquierda se ejecutará antes que el operando de su derecha. Las expresiones de la cláusula de inicio se ejecutan una sola vez, cuando arranca el bucle. Cualquier expresión legal se puede emplear en esta cláusula, aunque generalmente se utiliza para inicialización. Las variables se pueden declarar e inicializar al mismo tiempo en esta cláusula: for( int cnt=0; cnt < 2; cnt++ ) La segunda cláusula, de test, consiste en una única expresión que debe evaluarse a false para que el bucle concluya. En este caso, Java es mucho más restrictivo que C++, ya que en C, C++ cualquier expresión se puede evaluar a cero, que equivale a false. Sin embargo, en Java, esta segunda expresión debe ser de tipo booleano, de tal modo que se pueden utilizar únicamente expresiones relacionales o expresiones relacionales y condicionales. El valor de la segunda cláusula es comprobado cuando la sentencia comienza la ejecución y en cada una de las iteraciones posteriores. La tercera cláusula, de incremento, aunque aparece físicamente en la declaración de bucle, no se ejecuta hasta que se han ejecutado todas las sentencias que componen el cuerpo del bucle for; por ello, se utiliza para actualizar la variable de control. Es importante tener en cuenta que si utilizamos variables incluidas en esta tercera cláusula en las sentencias del cuerpo del bucle, su valor no se actualizará hasta que la ejecución de todas y cada una de las sentencias del cuerpo del bucle se haya completado. En esta cláusula pueden aparecer múltiples expresiones separadas por el operador coma, que serán ejecutadas de izquierda a derecha. El siguiente trocito de código Java que dibuja varias líneas en pantalla alternando sus colores entre rojo, azul y verde, utiliza un bucle for para dibujar un número determinado de líneas y una sentencia switch para decidir el color de la línea. Este fragmento sería parte de una función Java (método): int contador; for( contador=1; contador <= 12; contador++ ) { switch( contador % 3 ) { case 0: setColor( Color.red ); break; case 1: setColor( Color.blue ); break; case 2: setColor( Color.green ); break; } g.drawLine( 10,contador*10,80,contador*10 ); } También se soporta, como ya se ha indicado, el operador coma (,) en los bucles for, aunque su uso es una decisión de estilo, no es la única forma de codificar una sentencia lógica en particular. En ocasiones se utiliza como atajo, pero en otras se prefiere la utilización de sentencias múltiples dentro del cuerpo del bucle for. for( a=0,b=0; a < 7; a++,b+=2 ) Hay una característica que se admite en C++ y que Java no soporta. Se trata de que los compiladores actuales de C++ permiten la declaración de variables de control del bucle for con el mismo nombre que variables que se encuentren declaradas fuera del bucle. El ámbito de estas variables se limita al bucle. En el programa C++ java407.cpp, se declara una variable local de método llamada cnt y luego se declara como variable de control del bucle otra con el mismo nombre, cnt. El valor de las variables se visualiza en varios puntos del programa, de forma que la salida por pantalla sería la que se reproduce a continuación C:\> java407 Valor de la variable de metodo cnt: 5 Valor de la variable del bucle cnt: 0 Valor de la variable del bucle cnt: 1 Valor de la variable de metodo cnt: 5 Para compilar el programa se ha utilizado el compilador Borland C++ for Windows, versión 5.0. Java no soporta tal característica, no se pueden definir variables con el mismo nombre en dos sitios diferentes de un método. El programa java407.java, no compila, generando un error que indica que la variable cnt está declarada en el método cuando se intenta declararla en el bucle for. La salida de compilación es la que se muestra C:\>javac java407.java java407.java:32: Variable 'cnt' is already defined in this method. for( int cnt=0; cnt < 2; cnt++ ) ^ 1 error Si se elimina la línea en donde se declara e inicializa la variable local al método y la siguiente, en la que se imprime su valor, el programa sigue sin compilar. En este caso, el compilador indica que la variable cnt, que se encuentra en la sentencia final no está definida. Por tanto, el ámbito de la variable declarada dentro del bucle for parece está restringido al bucle en sí mismo. Si se eliminan las líneas en que interviene la variable global del método, el programa compila y se ejecuta correctamente, ilustrando el hecho de que Java soporta la declaración de variables en la cláusula de inicio del bucle,y además, que el ámbito de la variable está restringido al interior del bucle. La primera y tercera cláusulas del bucle for pueden encontrarse vacías, pero deben estar separadas por punto y coma (;). Hay autores que sugieren incluso que la cláusula de testeo puede estar vacía, aunque para el programador que está escribiendo esto, salvando el caso de que se trate de implementar un bucle infinito, si esta cláusula de comprobación se encuentra vacía, el método de terminación del bucle no es nada obvio, al no haber una expresión condicional que evaluar, por lo que debería recurrirse a otro tipo de sentencia, en vez de utilizar un bucle for. [inicialización;] while( terminación-expresión-booleana ) { sentencias; [iteración;] } El bucle while es la sentencia de bucle más básica en Java. Ejecuta repetidamente una vez tras otra una sentencia, mientras una expresión booleana sea verdadera. Las partes de inicialización e iteración, que se presentan entre corchetes, son opcionales. Esta sentencia while se utiliza para crear una condición de entrada. El significado de esta condición de entrada es que la expresión condicional que controla el bucle se comprueba antes de ejecutar cualquiera de las sentencias que se encuentran situadas en el interior del bucle, de tal modo que si esta comprobación es false la primera vez, el conjunto de las sentencias no se ejecutará nunca. Un ejemplo típico de utilización de este bucle es el cálculo de la serie de números de Fibonacci, que es una de las formas de conseguir la serie, y eso es precisamente lo que hace el ejemplo java408.java, cuyo código se muestra a continuación: class java408 { public static void main( String args[] ){ int max = 20; int bajo = 1; int alto = 0; System.out.println( bajo ); while( alto < 50 ) { System.out.println( alto ); int temp = alto; alto = alto + bajo; bajo = temp; } } } [inicialización;] do { sentencias; [iteración;] }while( terminación-expresión-booleana ); A veces se puede desear el ejecutar el cuerpo de un bucle while al menos una vez, incluso si la expresión booleana de terminación tiene el valor false la primera vez. Es decir, si se desea evaluar la expresión de terminación al final del bucle en vez de al principio como en el bucle while. Esta construcción do-while hace eso exactamente. |
|