UAA – Sistemas Electrónicos 2 Programación en Java Eduardo Serna-Pérez Sentencias de control De aquí en adelante será indispensable comenzar a elaborar programas que manejen expresiones y operaciones que inicialmente serán sencillas y que gradualmente demostraran las características, limitantes y beneficios de la programación en Java. Para esto partiremos primeramente de la declaración de la estructura básica más simple de un programa en Java. De manera que estaremos desarrollando soluciones un poco más elaboradas y modulares a partir del uso de métodos estáticos que es uno de los mecanismos más simples de funcionamiento en Java y que permite programar funciones independientes de clase alguna. 2.1 Unidad mínima de programación En Java la clase es la estructura primordial para el diseño de programas, todo programa en java debe ser inicializado, conceptualizado y visto como una clase, además todo programa Java arranca su operación desde la función main (principal). class NombreClase { public static void main (String [] args) { /* Cuerpo del programa principal */ } } La función main siempre debe ser vista como el punto de arranque para el diseño del programa completo, mas adelante veremos que los objetos no son mas que estructuras de datos complejas (es decir, tipos de datos abstractos) que interactúan entre sí. 2.1.1 Métodos estáticos La forma más sencilla de realizar programas de manera estructurada en java es empleando funciones o métodos estáticos, que son procedimientos o subrutinas medianamente independientes pero muy poco alejados del manejo de datos como en las clases. En realidad un método estático está involucrado de manera local a la clase que lo construye. Hasta el momento solo realizaremos métodos estáticos, pues necesitamos adquirir cierta habilidad antes de retomar nuevamente la construcción de clases. Como ya hemos mencionado la unidad mínima de programación en java es la clase, de manera que los métodos estáticos o procedimientos estarán declarados dentro de la clase, la sintaxis para la declaración de procedimientos estáticos es la siguiente: <modificador> class NombreClase { public static void main( String [] args ) { } <modificador> static <tipo> nombreProcedimiento(<argumentos>) { // declaración de variables locales // lista de sentencias } } 1 UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez Los modificadores de acceso permiten determinar el alcance del procedimiento en este caso será public, debido a que pretendemos que el procedimiento sea visto desde fuera de la clase principal, en otro caso podría ser omitido de manera que el procedimiento solo será visto de manera local a la clase (o paquete). El modificador static determina que se trata de un procedimiento de clase por lo que no será necesario construir un objeto de la clase para poder emplear dicho procedimiento. El tipo de dato que regresará el procedimiento varía según del tipo y características de la función, los tipos de datos disponibles podrían ir desde tipos de datos nativos (int, flota, void, char, etc) hasta tipos de datos referenciados (arreglo, String, wrapper o un tipo de dato definido por el usuario “un objeto de clase”). La lista de argumentos son todos aquellos valores que requieren ser enviados a una función para que pueda realizar sus sentencias, estos argumentos pueden ser desde tipos de datos nativos hasta referenciados. Es importante recordar que las variables definidas dentro de los métodos son llamadas variables locales (algunas veces llamadas variables automáticas, temporales o de pila), éstas deben ser inicializadas explícitamente antes de ser usadas y son vistas únicamente por la función. Suponga que requerimos construir un procedimiento suma que nos permita sumar un par de valores: public class Main { public static void main(String[] args) { int x = 1, y = 2, z; z = suma(x,y); System.out.print("el resultado es " + z); } static int suma(int a, int b){ return a+b; } } Observe que el modificador de acceso puede ser omitido si se trata de una función local a la clase principal, de manera que el procedimiento recibe un par de valores y devuelve el resultado. import static java.lang.System.out; class Prueba { public static void main(String [] args) { int [] x = {2,3,5,6, 9,1,0}; out.println("la suma es " + suma(x)); } static int suma( int [] tem ) { int r = 0; for (int i = 0; i < tem.length; i++) r+= tem[i]; return r; } } Inclusive podemos integrar el concepto de sobrecarga que ya se tiene claramente entendido: 2 UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez import static java.lang.System.out; class Prueba { public static void main(String [] args) { int [] x = {2,3,5,6, 9,1,0}; int val = 10; out.println("la suma en x[0] y val con es "+suma(x[0], val)); out.println("la suma del arreglo es " + suma(x)); return; } static int suma(int a, int b){ return a+b; } static int suma( int [] tem ) { int r = 0; for (int i = 0; i < tem.length; i++) r+= tem[i]; return r; } } Las variables locales son creadas cuando se realiza la ejecución de un método y son destruidas al finalizar el método, a esto se debe el nombre de variables temporales. Las variables locales deben ser inicializadas manualmente antes de ser usadas. El compilador genera un error si puede determinar una condición donde las variables son usadas antes de ser inicializadas. En la siguiente unidad veremos mas a detalle esta característica de construcción de programas empleando el mecanismo de orientación a objetos. Por el momento emplearemos solo funciones estáticas a la clase para elaborar programas sencillos. 2.2 Estructuras de decisión Las estructuras de decisión son estatutos condicionales que nos permiten la ejecución selectiva de porciones de programa (bloques de código) de acuerdo al valor de una expresión. Java soporta los estatutos if y switch, que nos permiten ramificaciones de ejecución en dos o mas ramas. 2.2.1 Sentencia if – else La sintaxis de la sentencia es: if ( <expresión booleana>) [ { ] <bloque de estatutos si la expresión es cierta> [ } ] else [ { ] <bloque de estatutos si la expresión es falsa> [ } ] Ejemplo: public class EjemploIF { 3 UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez public static void main(String [] arg) { int x = (int)(Math.random() * 100); if (x > 50) System.out.println("Mayor a 50 "+x); else { System.out.println("Menor a 50 "+x); x = 0; } } } 2.2.2 Sentencia switch La sintaxis de la sentencia es: switch ( <expresión>) { case <constante1> : <bloque de estatutos> [break;] case <constante2> : <bloque de estatutos> [break;] default : <bloque de estatutos> [break;] } En el estatuto switch el valor de la expresión debe ser compatible con un entero y puede existir la promoción. La etiqueta default especifica que el segmento de código será ejecutado si el valor de la expresión nunca coincide con alguno de los casos. Una estatuto return puede ser usado en lugar de break. Además, si switch esta en un ciclo, el estatuto continue permitira la salida del estatuto switch. Por ejemplo: class Switch1{ public static void main(String args[]){ int k = (int)(Math.random() * 16); switch(k){ case 2: System.out.println(" case k = 2"); break; case 4: System.out.println(" case k = 4"); break; case 8: System.out.println(" case k = 8"); break; default: System.out.println(" case default " + k); } } } 4 UAA – Sistemas Electrónicos 2.3 Programación en Java Eduardo Serna-Pérez Estructuras de repetición Las estructuras de repetición nos permiten ejecutar bloques de código de manera repetitiva. Java soporta 3 tipos de estructuras de repetición: for, while y do. Los ciclos for y while, verifican la condición antes de ejecutar el bloque del ciclo. Mientras que do ejecuta el bloque de código y verifica la condición al final. La sintaxis para el estatuto for es: for(<inicia expresión>; <verifica expresión>; <altera expresión>) [{] <estatuto o bloque> [}] Ejemplo: public class ForLoop { public static void main(String[] args) { for ( int i = 0; i < 10; i++ ) System.out.println(i + " el cuadrado es " + (i*i)); } } Ejemplo: import static java.lang.System.out; class Prueba { public static void main(String [] args) { int [] x = {2,3,5,6,4,1,0}, y = {5,4,2,1,3,6,7}; out.println("el producto escalar es " + prodEscalar(x,y)); return; } static int prodEscalar( int [] a, int [] b ) { int r = 0; for (int i = 0; i < a.length; i++) r+= (a[i] * b[i]); return r; } } Ejemplo: import static java.lang.System.out; class Prueba { public static void main(String [] args) { int [][] x = {{2,3},{5,6},{4,1}}; double [][] r = null; double e = 4.0; 5 UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez r = matPorEscalar(x,e); out.println("la matriz es "); mostrar(r); return; } static double [][] matPorEscalar( int [][] tem, double n ) { double [][] res = new double [tem.length][tem[0].length]; for (int i = 0; i < tem.length; i++) for (int j = 0; j < tem[i].length; j++) res[i][j] = tem[i][j] * n; return res; } static void mostrar( double [][] tem) { for (int i = 0; i < tem.length; i++) { for (int j = 0; j < tem[i].length; j++) out.print(tem[i][j] + " "); out.println(); } return; } } La sintaxis para el estatuto while es: while (<verifica expresión>) [{] <estatuto o bloque> [}] class While { public static void main(String [] arg) { int i = 1; while (i < 5) { System.out.println("i = "+ i); i++; } } } La sintaxis para el estatuto do/while es: do [{] <estatuto o bloque> [}] while (<verifica expresión>) class DoWhile { public static void main(String [] arg) { int i = 1; do { System.out.println("i = "+ i); 6 UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez i++; } while (i < 5); } } 2.3.1 Sentencia break, continue y return En algunos casos se tendrá la necesidad de eliminar o modificar la iteración en bucle de control, para ello se pueden emplear las etiquetas break y continue. • break: Rompe el flujo de un bloque switch y de repetición mas cercano a él. Lo que provoca que el flujo de control sea roto y se salga intempestivamente de ciclo. do { lista-de-estatutos; if (condición) { break; } lista-de-estatutos; } while (expresion); // break provoca que el flujo continué aquí • continue: Realiza un salto al final del ciclo de control (verificación) y se reintegra al ciclo de control. do { lista-de-estatutos; if (condición) { continue; } lista-de-estatutos; } while (expresion); • return: Realiza el regreso de llamada a función en cualquier punto que se encuentre. 2.3.2 Sentencia for-each Es una sentencia que actúa con elementos que son catalogados como elementos iteradores. import static java.lang.System.out; class Prueba { public static void main(String [] args) { int [] x = {2,3,5,6,4,1}; out.println("la matriz es "); mostrar(x); return; } static void mostrar( int [] tem) { 7 UAA – Sistemas Electrónicos Programación en Java for ( int i : tem ) out.print( i + " return; Eduardo Serna-Pérez "); } } 2.3.3 Aplicando sentencias de control y métodos estáticos A continuación emplearemos el diseño de una función estática muy simple con el objetivo de ver la independencia de la función y mostrar de manera clara lo referente al paso de parámetros que sigue siendo parte fundamental en la construcción de herramientas modulares. public class Sumatoria { public static void main( String args[] ) { int f = 5, c = 2; double m[][] = new double [f][c]; System.out.print("numero de filas " + f); System.out.print("numero de columnas " + c); for ( int i = 0; i < m.length; i++ ) { for ( int j = 0; j < m[i].length; j++ ) m[i][j]= Math.random(); } for ( int i=0; i < m.length; i++ ) { for ( int j=0; j < m[i].length; j++ ) System.out.print(" ("+ i +"," + j + ") -> " + m[i][j]); System.out.println(); } System.out.println(" sumatoria " + sumatoria(m)); System.exit(0); } public static double sumatoria(double [][] lista) { double total = 0; for( int i = 0; i < lista.length; i++ ) for ( int j = 0; j < lista[i].length; j++ ) total += lista[i][j]; return total; } } Es importante observar como el paso de parámetros se puede realizar con cualquier tipo de dato reconocido por la sintaxis de java, en éste caso tomamos una matriz y la enviamos como parámetro a una función que se encargara de procesarla para una sumatoria de sus elementos que la componen, al final regresa como valor el resultado de dicha operación. Una versión un poco distinta, pero versando sobre la misma idea de manipulación de datos compuestos como las matrices es la siguiente, observe que en éste caso se emplean un par de procedimientos. El primero se encarga de recolectar los datos para llenar una matriz con números aleatorios, posteriormente los datos son transferidos a una matriz local a la función main la cual se encargara de transferir dicho dato a otro procedimiento vacío(void). 8 UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez public class Captura { // metodo principal de la clase public static void main( String args[] ) { int filas = 5, columnas = 2; double matriz[][] = llenadoAleatorio(filas, columnas); mostrar(matriz); return; } // procedimiento que alimenta un matriz con datos y la regresa como // resultado static double [][] llenadoAleatorio(int f, int c){ // argumentos filas y columnas double mat[][] = new double [f][c]; //matriz local System.out.println("filas, columnas " + f+","+c); for ( int i = 0; i < mat.length; i++ ) { for ( int j = 0; j < mat[i].length; j++ ) mat[i][j]= Math.random(); // llenado aleatorio } return mat; // matriz de regreso } // procedimiento que muestra el contenido de una matriz recibida // como argumento static void mostrar(double [][] mat){ for ( int i=0; i < mat.length; i++ ) { for ( int j=0; j < mat[i].length; j++ ) System.out.print(" ("+ i +"," + j + ") -> "+ mat[i][j]); System.out.println(); } return; } } Finalmente una versión alternativa para la suma de matrices podría verse de la siguiente manera: public class Matrices { /** * @param args the command line arguments */ public static void main(String[] args) { // TODO code application logic here double [][] x = {{1,2},{3,4}}; double [][] y = {{4,3},{2,1}}; double [][] res = suma( x, y ); mostrar(res); } /** * Funcion que realiza una suma de matrices, los argumentos son * un par de matrices flotantes */ public static double [][] suma( double [][] a, double [][] b ) { if (a.length != b.length || a[0].length != b[0].length) return null; 9 UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez double [][] calc = new double [a.length][a[0].length]; for (int f = 0; f < calc.length; f++) for(int c = 0; c < calc[f].length; c++) calc[f][c] = a[f][c] + b[f][c]; return calc; } /* * Funcion que despliega el contenido de una matriz */ public static void mostrar( double [][] m ) { for (int f = 0; f < m.length; f++){ System.out.println(); for(int c = 0; c < m[f].length; c++) System.out.print(m[f][c]+"\t"); } return; } } 2.4 Entornos de desarrollo La 10 UAA – Sistemas Electrónicos Programación en Java Eduardo Serna-Pérez Bibliografía Nell Dale, Chip Weems, Mark Headington, Programming and Problem Solving whith Java, Jones & Bartlett, 2005, ISBN: 0-7637-3069-6. Luis Joyanes Aguilar y Matilde, Java 2 Manual de programación, Osborne-Mc Graw Hill. 11