Está en la página 1de 58

Lenguaje Programacin Java

Gua del Estudiante

Mapa del Curso

Lenguaje Bsico de Programacin


Caracteristicas De Java Identificadores Palabras Reserv. Tipos de datos Expresiones Control de Flujo de programas Manejo de Arreglos

Programacin Orientada a Objetos


Clases y Objetos Caracteristicas avanzadas

Manejo de Errores
Excepciones

Applets
Introduccion Java Applets

Desarrollo de Aplicaciones Graficas


Construyendo GUIs Modelo de Eventos AWT Librera de Componentes AWT Java Foundation Classes

Multiprogramacin
Threads

Comunicaciones
Archivos Streams I/O

Networking

Modulo 1 Lenguaje Bsico de Programacin.


Caractersticas de Java.
Las caractersticas principales que nos ofrece Java respecto a cualquier otro lenguaje de programacin, son: Simplicidad Java ofrece toda la funcionalidad de un lenguaje potente, pero sin las caractersticas menos usadas y ms confusas de stos. Java elimina muchas de las caractersticas de otros lenguajes como C++, para mantener reducidas las especificaciones del lenguaje y aadir caractersticas muy tiles como el garbage collector (reciclador de memoria dinmica). En Java ya no es necesario preocuparse de liberar memoria. Reduce en un 50% los errores ms comunes de programacin con lenguajes como C y C++ al eliminar muchas de las caractersticas de stos, entre las que destacan: aritmtica de punteros no existen referencias registros (struct) definicin de tipos (typedef) macros (#define) necesidad de liberar memoria (free) Orientado a Objetos Java implementa la tecnologa bsica de C++ con algunas mejoras Java trabaja con sus datos como objetos y con interfaces a esos objetos. Soporta las tres caractersticas propias del paradigma de la orientacin a objetos: encapsulacin, herencia y polimorfismo. Distribuido Java se ha construido con extensas capacidades de interconexin TCP/IP. Existen libreras de rutinas para acceder e interactuar con protocolos como http y ftp. Esto permite a los programadores acceder a la informacin a travs de la red con tanta facilidad como a los ficheros locales. Independiente de la Plataforma Para establecer Java como parte integral de la red, el compilador Java compila su cdigo a un fichero objeto de formato independiente de la arquitectura de la mquina en que se ejecutar. Cualquier mquina que tenga el sistema de ejecucin (run-time) puede ejecutar ese cdigo objeto, sin importar en modo alguno la mquina en que ha sido generado. Actualmente existen sistemas run-time para Solaris 2.x, SunOs 4.1.x, Windows 95, Windows NT, Linux, Irix, Aix, Mac, Apple y probablemente haya grupos de desarrollo trabajando en el porting a otras plataformas.

El cdigo fuente Java se "compila" a un cdigo de bytes de alto nivel independiente de la mquina. Este cdigo (byte-codes) est diseado para ejecutarse en una mquina hipottica que es implementada por un sistema run-time, que s es dependiente de la mquina. En una representacin en que tuvisemos que indicar todos los elementos que forman parte de la arquitectura de Java sobre una plataforma genrica, obtendramos una figura como la siguiente:

En ella podemos ver que lo verdaderamente dependiente del sistema es la Mquina Virtual Java (JVM) y las libreras fundamentales, que tambin nos permitiran acceder directamente al hardware de la mquina. Adems, habr APIs de Java que tambin entren en contacto directo con el hardware y sern dependientes de la mquina.

Robusto Java realiza verificaciones en busca de problemas tanto en tiempo de compilacin como en tiempo de ejecucin. La comprobacin de tipos en Java ayuda a detectar errores, lo antes posible, en el ciclo de desarrollo. Java obliga a la declaracin explcita de mtodos, reduciendo as las posibilidades de error. Maneja la memoria para eliminar las preocupaciones por parte del programador de la liberacin o corrupcin de memoria. Tambin implementa los arrays autnticos, en vez de listas enlazadas de punteros, con comprobacin de lmites, para evitar la posibilidad de sobreescribir o corromper memoria resultado de punteros que sealan a zonas equivocadas. Estas caractersticas reducen drsticamente el tiempo de desarrollo de aplicaciones en Java. Adems, para asegurar el funcionamiento de la aplicacin, realiza una verificacin de los bytecodes, que son el resultado de la compilacin de un programa Java. Es un cdigo de mquina virtual que es interpretado por el intrprete Java. No es el cdigo mquina directamente entendible por el hardware, pero ya ha pasado todas las fases del compilador: anlisis de instrucciones, orden de operadores, etc., y ya tiene generada la pila de ejecucin de rdenes. Java proporciona, pues: Comprobacin de punteros Comprobacin de lmites de arrays Excepciones Verificacin de byte-codes Multiprogramacin Al ser multithreaded (multihilvanado, en mala traduccin), Java permite muchas actividades simultneas en un programa. Los threads (a veces llamados, procesos ligeros), son bsicamente pequeos procesos o piezas independientes de un gran proceso. Al estar los threads construidos en el lenguaje, son ms fciles de usar y ms robustos que sus homlogos en C o C++. El beneficio de ser multithreaded consiste en un mejor rendimiento interactivo y mejor comportamiento en tiempo real. Aunque el comportamiento en tiempo real est limitado a las capacidades del sistema operativo subyacente (Unix, Windows, etc.), an supera a los entornos de flujo nico de programa (single-threaded) tanto en facilidad de desarrollo como en rendimiento.

Identificadores Palabras Reservadas - Tipos de Datos


Tipos de Datos Hay ocho tipos bsicos de datos llamados primitivos. Enteros con signo. byte (8 bits). short (16 bits). int (32 bits). long (64 bits). Numricos de punto flotante: float double Carcter simple: se utiliza para caracteres individuales como letras, nmeros, puntuacin, y otros smbolos. char Booleanos: que pueden albergar los valores true false. boolean

Tipos de Clases String: Es un tipo de clase usado para almacenar texto Ejemplo colorDePelo = castao; Cuando una variable tiene una clase como su tipo, la variable se refiere a un objeto de esa clase o a una de sus subclases. Si se declara a un tipo de variable Object significa que puede contener cualquier objeto. Declaracin de variables Se declaran anteponiendo el tipo de dato o clase a la cual pertenecen. Para las variables del mismo tipo, se pueden declarar en la misma lnea separndolas por comas.. Ejemplo int total; String ciudad, calle, provincia = Buenos Aires ; boolean activo = true; Nomenclatura de Variables Los nombres de variables deben comenzar con una letra, un carcter de subrayado ( _ ) o un signo pesos ($). No pueden empezar con un nmero. Despus del primer carcter pueden incluir cualquier combinacin. Java es sensible a minsculas y maysculas, esto permite tener una variable llamada X y otra llamada x. El estndar recomendado es para el nombramiento de variables es: La primera letra minscula. Cada palabra despus del nombre de la variable empieza con mayscula. (Ej. areaCodigo) Todas las dems letras son minsculas Comentarios Hay tres formas de aplicar comentarios en la definicin de una clase, que son: Para comentarios de una lnea //. Todo lo que se encuentre a partir de ah hasta el final de la lnea es considerado comentario. Para comentarios de mas de una lnea: Se utilizan los smbolos /* - */ con los que se encierra el comentario. Para los comentarios que son autodocumentables se utilizan los smbolos /** - */. Ejemplos // Comentario de una lnea /* Comentario de mas de una lnea. */ /** Documentacin de un mtodo o atributo.... */

Literales Un literal es cualquier nmero, texto o informacin que representa directamente un valor. Literales numricos Para representar un literal de tipo long anteponga una L al nmero (long total = 10L;) Para representar un literal negativo anteponga un (long total = -10L;) Para representar un literal con notacin octal anteponga un 0 al nmero (int total = 010;) Para representar un literal con notacin hexadecimal anteponga un 0x al nmero (int total = 0xFF;) Para representar un literal de punto flotante se utiliza un punto (.) para el punto decimal (double numero = 2.50;), todas estas literales se consideran double. Para especificar un literal de punto flotante como float anteponga la letra f (f o F) (float numero = 3.1416F;) Para representar notacin exponencial utilice la letra e (double x = 12e22;) Literales booleanos Los valores true y false son literales, y son los nicos valores posibles para las variables booleanas Literales de caracteres Es un carcter sencillo entre comillas sencillas como a, # y 3. Literales de cadena Es una cadena de caracteres entre comillas dobles como Esto es una cadena. Como las cadenas en Java son objetos reales, contienen mtodos para combinar cadenas, modificarlas y determinar si dos cadenas poseen el mismo valor. Java almacena el valor de una cadena como un objeto String, por lo tanto solo se debe crear un nuevo objeto explcitamente, por lo que son tan fciles de utilizar como los tipos de dato bsicos.

Expresiones Control de Flujo - Arreglos


Expresiones y Operadores Una expresin es una instruccin que produce un valor. Por ejemplo: int x = 3; int y = 4; int z = x * y; // Expresin Un operador es un smbolo especial utilizado para funciones matemticas, algunos tipos de instrucciones de asignacin y comparaciones lgicas. Por ejemplo el * de la expresin anterior. Operadores Aritmticos Suma + Resta Multiplicacin * Divisin / Mdulo % El lado derecho de una expresin siempre se calcula antes de que se d la asignacin. Por esta razn la siguiente expresin es posible: int x = 5; x = x + 2; Donde x ahora es 7.

Incremento y Decremento Sirven para aadir o sustraer 1 a una variable. Para incrementar se utiliza ++ (int x = 7; x = x++; ahora x vale 8). Para decrementar se utiliza - - (int x = 7; x = x - -; ahora x vale 6). Comparaciones Son operaciones para hacer comparaciones entre las variables, variables y literales, u otros tipos de informacin. Devuelven siempre un valor booleano. Igual == Distinto = Menor que < Mayor que > Menor que o igual a <= Mayor que o igual a >= Operadores Lgicos Las expresiones que producen valores booleanos, como las operaciones de comparacin, se pueden combinar para formar expresiones ms complejas. Esto se maneja a travs de operadores lgicos, los cuales para las combinaciones lgicas: AND: & o && (con && el lado derecho de la expresin nunca se evala), devuelve true solo si las dos expresiones son verdaderas. OR: | o || (con || el lado derecho de las expresin nunca se evala), devuelve true si alguna de las expresiones son verdaderas. XOR: ^, devuelve true solo si las dos expresiones booleanas que combina tienen valores opuestos. Si ambas son true o false, devuelve false. NOT. !, invierte el valor de una expresin booleana de la misma manera en que un smbolo menos invierte el signo positivo en un nmero. Precedencia de operadores Es el orden de evaluacin que posee Java cuando hay mas de un operador en una expresin. El orden del primero al ltimo es: Operaciones de incremento y decremento Operaciones aritmticas Comparaciones Operaciones lgicas Expresiones de asignacin Para cambiar el orden en que se evalan las operaciones se deben colocar parntesis en las expresiones que se quieren evaluar primero.

Aritmtica de cadenas El operador + tambin puede ser utilizado para concatenar cadenas. El operador + combina cadenas, objetos y variables para formar una cadena sencilla. Tambin esta el operador corto += que aade algo al final de la cadena. Ejemplo miNombre += Seor; Controles de Flujo Estructuras de decisin o salto Instrucciones if else Estructura: if (expresin boolean) { //Bloque de cdigo para expresiones verdaderas; } else { // Bloque de cdigo para expresiones falsas; } Siempre debe tomar una expresin booleana. El else es opcional y puede ser omitido si no existen acciones a tomar en caso de no cumplirse la condicin Instruccin switch Estructura: Switch (expresin 1) { Case constante2: Bloque de cdigo; Break; Case constante3: Bloque de cdigo; Break; Default: Bloque de cdigo; Break; } La expresin 1 debe ser compatible con un tipo de dato entero. Los tipos de punto flotante, long o clases no estn permitidas. El default es opcional, y es utilizado para especificar un segmento de cdigo que es ejecutado si la variable o expresin no matchea con ninguno de los case. Si no hubiera un break como ltima instruccin dentro del cdigo del case, el programa entrara al cdigo del prximo case sin evaluar la expresin.

Estructuras de Iteracin Las estructuras de lazo permiten repetir la ejecucin del bloque de cdigo que contengan. En java existen tres tipos: for, while y do. For y while evalan la condicin de lazo antes de ejecutar el bucle. Do evala despus de ejecutar el bucle. En este caso el bucle se ejecuta al menos una vez. Instruccin for Estructura: For (expresin inicial; expresin booleana; alter_expresion3) { Bloque de cdigo; } En esta estructura est permitido utilizar comas para separar variables, Ejemplo for (int i = 0, j = 0; j < 10; i++, j++) { Bloque de cdigo; } La variable i es solo accesible dentro del bloque del for. Instruccin while Estructura: While (boolean) { Bloque de cdigo; } Hay que asegurarse de que la variable utilizada en el while est definida y sea verdadera antes de la ejecucin del mismo. Instruccin do Estructura: Do { Bloque de cdigo; } while (expresin booleana); Hay que asegurarse de que la variable utilizada en el while est definida y sea verdadera antes de la ejecucin del mismo. Instrucciones especiales dentro de las estructuras de lazo: Break [label]; // Es utilizada para salir de las instrucciones del switch, de las estructureas de lazo y de los bloques con etiqueta de forma prematura. Continue [label]; // Es usada para saltear el cdigo y llegar hasta el final dentro de las estructuras de lazo. Label : instruccin; // Identifica con un nombre una instruccin vlida a la que se le tranferir el control.

Ejemplo: Do { Bloque de cdigo; If (condicin es true) Break; } while (expresin booleana); Do { Bloque de cdigo; If (condicin es true) continue; } while (expresin booleana); loop: Do { //label

instruccin; Do { instruccin; instruccin; If (condicin es true) Break loop; } while (expresin booleana); instruccin; } while (expresin booleana); Palabras reservadas Las siguientes son las palabras reservadas que estn definidas en Java y que no se pueden utilizar como indentificadores: abstract boolean break byte byvalue case catch char class const continue default Do double Else extends False Final Finally Float for goto if implements import instanceof int interface long native new null package private protected public return short static super switch synchronized this threadsafe throw transient true try void while

Arreglos Declaracin: Se utilizan para agrupar objetos del mismo tipo y nombrarlos con un nombre comn. Ejemplo: char s[]; Point p[]; //Point es una clase La declaracin de un array crea una referencia que puede ser utilizada para referirlo, o sea que la memoria del array solo se utiliza cuando ste es creado por medio de la instruccin new. Creacin: Los arrays se crean como el resto de los objetos, utilizando la instruccin new. Ejemplo: s = new char[20]; p = new Point [100]; La instruccin p[0] = new Point[]; Indica que se est creando el elemento uno del array, el sub cero ([0]), es el indice del array. Inicializacin: Cuando se crea un array se debe inicializar cada uno de sus elementos, no deben utilizarse antes de este paso. Ejemplo: String nombres[] = { Juan, Maria, Laura }; Arreglos Multidimensionales: En java se pueden crear arrays de arrays, y arrays de arrays de arrays. Ejemplo: Int dosDim [][] = new int [4][]; dosDim[0] = new int [5]; dosDim[1] = new int [5]; En el primer caso se crea un array de 4 elementos, cada elemento es una referencia nula a un elemento de tipo array de enteros, y ser inicializado separadamente. Por esta razn es posible crear arrays de arrays no rectangulares. Ejemplo: int dosDim [][] = new int [4][]; dosDim[0] = new int [5]; dosDim[1] = new int [2]; dosDim[2] = new int [4]; dosDim[3] = new int [8]; Hay otra forma ms corta de inicializar un array de array: int dosDim [] [] = new int [4] [5]; El atributo length es utilizado para determinar el largo del array, y es muy til a la hora de iterar dentro del mismo.

Ejemplo: int lista [] = new int [10]; for (int i = 0; i< lista.length; i++) { System.out.println (lista[i]); } Redimensionamiento de arrays Al crearse un array ste no puede ser redimensionado, pero s se puede utilizar la misma variable para referenciar un nuevo array. Ejemplo: int miArray[] = new int [6]; miArray = new int [10]; El primer array es perdido a menos que otra referencia lo haya guardado. Copia de arrays Java provee un mtodo especial de la clase System, arraycopy(), para copiar arreglos. Ejemplo: System.arraycopy(miArray, 0, otroArray, 0, miArray.length);

Modulo 2 - Programacin Orientada a Objetos.


Conceptos Principales Encapsulacion. Herencia. Polimorfismo.

Clase: Definicion de atributos y comportamientos de un objeto de la realidad. Cada clase se define en un solo archivo de cdigo fuente (.java) que lleva el nombre de la misma. Objeto: Instancia particular de una clase. Definicin de Clases: [package nombrepaquete] [import nombreclase] [Modificadores] class NombreClase [extends SuperClase] [implements Interfase] { [definicin de atributos] [definicin de metodos]

Ejemplos: Definicin de una clase: public class Empleado { String Nombre; String Apellido; String Gerencia; } Las variables Nombre, Apellido y Gerencia son los atributos de la clase empleado. Definicin de un Objeto y utilizacin de sus atributos. Empleado emp = new Empleado(); emp.Nombre = Juan; emp.Apellido = Perez; emp.Gerencia = Administracin;

Definicin de Mtodo: [Modificadores] tiporetorno NombreMetodo ( [Lista de Argumentos] ) { Bloque de Cdigo; } Ejemplo public class String String String Empleado { Nombre; Apellido; Gerencia;

public void addDays (int days) { Bloque de cdigo del mtodo; } } Este mtodo llamado addDays recibe como parmetro la variable de tipo entera (int) days y no devuelve valores (void). Empleado emp = new Empleado(); emp.Nombre = Juan; emp.Apellido = Perez; emp.Gerencia = Administracin; emp.addDays(4); This La palabra reservada This es utilizada para hacer referencia al objeto actual. Ejemplo public class MyDate{ int day, month, year; public int mostrarDia(){ return this.day; } } Encapsulamiento Para encapsular los atributos de una clase se utiliza el modificador private antepuesto al tipo de dato del mismo. Y se construyen dos mtodos (para los casos en que aplique) con el modificador public, que alteren y muestren el contenido del mismo.

Ejemplo public class MyDate { private int day; private int month; private int year; // Mtodo de alteracin del contenido del atributo. public void setDay(int newvalueofday){ //validaciones del nuevo valor. this.day = newvalueofday; } // Mtodo para mostrar el valor. public int getDay(){ return this.day; }

Sobrecarga de Mtodos En ciertas circunstancias se necesitan desarrollar varios mtodos en una misma clase que bsicamente hacen la misma tarea, pero con diferentes argumentos. Podemos considerar un mtodo simple que solo imprima una lnea de texto. Este mtodo lo podemos llamar imprimirLinea(). Ahora supongamos que necesitamos diferentes mtodos de impresin para cada uno de los siguientes tipos de datos: int, float,String, ya que es razonable que cada uno se imprima de manera distinta. Se podran crear tres mtodos, uno para cada tipo de datos que se podran llamar imprimirLineaInt(); imprimirLineaFloat();imprimirLineaString() respectivamente aunque esto es tedioso. Java permite reutilizar los nombres de los mtodos solo si, difieren en los argumentos que recibe o el tipo de dato que retorna, en caso contrario la clase no compilara. Ejemplo. public void imprimirLinea (int i); public void imprimirLinea (float f); public void imprimirLinea (String s); Constructores Los constructores son mtodos especiales que se ejecutan por nica vez en el momento de creacin de una instancia de una clase (objeto), con el fin de inicializar el contenido de sus atributos. Los constructores son identificados por las siguientes caractersticas: a) El nombre del mtodo se corresponde exactamente con el nombre de la clase. b) El mtodo no devuelve ningn tipo de dato.

Ejemplos 1) Un solo Constructor: public class Xyx{ // Declaracin de atributos... public Xyz(){ // Inicializacin del objeto } // resto de los mtodos. } 2) Sobrecarga de Constructores: public class Employee{ // Declaracin de atributos private String name; private int salary; public Employee(String n, int s) { this.name = n; this.salary = s; } public Employee(String n) { this(n,0); } public Employee() { this(Unknow); } } // resto de los mtodos.

Los constructores son invocados solo con la utilizacin de la instruccin new. Si la clase no tiene una definicin explicita de constructor, el lenguaje de programacin le provee uno en tiempo de ejecucin. Este constructor no recibe ningn parmetro y no efecta ninguna operacin, solo se utiliza para poder instanciar nuevos objetos con la instruccin new. Herencia En Java solo se puede heredar de una sola clase (herencia simple), esto permite definir una clase en base a otra ya creada. Esto se define mediante la palabra extends, y se heredan todos los mtodos y los atributos de la superclase. No son heredables los constructores. Si no se definiera en forma explicita la herencia desde una clase se heredara de la clase Object por defecto.

Ejemplo. public class Persona { private String nombre; private String apellido; public void cambiarNombre( String nuevonombre) { nombre = nuevonombre; } } public class Empleado extends Persona { private String cargo; public String getCargo(){ return cargo; } } Empleado emp = new Empleado(); emp.cambiarNombre(Carlos); Super La palabra super se utiliza para referirse a mtodos y/o atributos de la superclase. Generalmente se la utilizar para reescribir mtodos heredados sin reemplazar su funcionamiento sino agregndole la nueva funcionalidad. Ejemplo public class Empleado { private string nombre; private int sueldo; public String getDetalles(){ return Nombre: + nombre + Sueldo: + } sueldo;

public class Gerente extends Empleado { private String gerencia; public String getDetalles() { return super.getDetalles() + Gerencia: + gerencia; } } Gerente ger = new Gerente(); ger.nombre = Jose; ger.sueldo = 3000; ger.gerencia = Administracin; System.out.println(ger.getDetalles()); La salida ser: Nombre: Jose Sueldo: 3000 Gerencia: Administracion

Clases Abstractas Una de las caractersticas ms tiles de cualquier lenguaje orientado a objetos es la posibilidad de declarar clases que definen como se utiliza solamente, sin tener que implementar mtodos. Esto es muy til cuando la implementacin es especfica para cada usuario, pero todos los usuarios tienen que utilizar los mismos mtodos. Un ejemplo de clase abstracta en Java es la clase Graphics: public abstract class Graphics { public abstract void drawLine( int x1,int y1,int x2, int y2 ); public abstract void drawOval( int x,int y,int width, int height ); public abstract void drawArc( int x,int y,int width, int height,int startAngle,int arcAngle ); . . . } Los mtodos se declaran en la clase Graphics, pero el cdigo que ejecutar el mtodo est en algn otro sitio: public class MiClase extends Graphics { public void drawLine( int x1,int y1,int x2,int y2 ) { <cdigo para pintar lneas -especfico de la arquitectura-> } } Cuando una clase contiene un mtodo abstracto tiene que declararse abstracta. No obstante, no todos los mtodos de una clase abstracta tienen que ser abstractos. Las clases abstractas no pueden tener mtodos privados (no se podran implementar). Una clase abstracta tiene que derivarse obligatoriamente, no se puede hacer un new de una clase abstracta. Interfaces Los mtodos abstractos son tiles cuando se quiere que cada implementacin de la clase parezca y funcione igual, pero necesita que se cree una nueva clase para utilizar los mtodos abstractos. Los interfaces proporcionan un mecanismo para abstraer los mtodos a un nivel superior. Un interface contiene una coleccin de mtodos que se implementan en otro lugar. Los mtodos de una clase son public, static y final. La principal diferencia entre interface y abstract es que un interface proporciona un mecanismo de encapsulacin de los protocolos de los mtodos sin forzar al usuario a utilizar la herencia. Por ejemplo: public interface VideoClip { // comienza la reproduccin del video void play(); // reproduce el clip en un bucle void bucle(); // detiene la reproduccin void stop(); } Las clases que quieran utilizar el interface VideoClip utilizarn la palabra implements y proporcionarn el cdigo necesario para implementar los mtodos que se han definido para el interface: class MiClase implements VideoClip { void play() { <cdigo> } void bucle() { <cdigo> } void stop() { <cdigo> }

Al utilizar implements para el interface es como si se hiciese una accin de copiar-y-pegar del cdigo del interface, con lo cual no se hereda nada, solamente se pueden usar los mtodos. La ventaja principal del uso de interfaces es que una clase interface puede ser implementada por cualquier nmero de clases, permitiendo a cada clase compartir el interfaz de programacin sin tener que ser consciente de la implementacin que hagan las otras clases que implementen el interface. class MiOtraClase implements VideoClip { void play() { <cdigo nuevo> } void bucle() { <cdigo nuevo> } void stop() { <cdigo nuevo> } Agrupando Clases Empaquetando Java provee un mecanismo de agrupacin de clases relacionadas en Paquetes. Se puede indicar en la definicin de la clase a que paquete o grupo pertenece la misma utilizando la instruccin package. Solo una declaracin de paquete se permite por clase y por archivo de cdigo fuente. Los nombres de paquetes deben ser jerrquicos y las jerarquas estar separadas por puntos. La definicin de paquete debe estar al comienzo del archivo de cdigo fuente. Ejemplo package telecom.sistemas; public class Empleado { //Contenido de la clase. } Importacin Para poder utilizar el contenido de los paquetes en nuestras clases debemos decirle al compilador java donde encontrarlas. De hecho el nombre del paquete forma parte del nombre de la clase, y uno se puede referir a la clase como telecom.sistemas.Empleado o simplemente como la clase Empleado. Puedo agregar tantas importaciones como necesite. Ejemplos import java.applet.Applet; import java.awt.*; public class Empleado extends Applet { contenido de la clase: }

Ejemplo Completo public class Persona { //Atributos. private String nombre; private String apellido; private int edad; //Metodos Constructores. public Persona(String nom, String ape, int eda){ this.setNombre(nom); this.setApellido(ape); this.setEdad(eda); } public Persona(String nom, String ape){ this(nom,ape,1); } public Persona(String nom){ this(nom,"Sin Apellido"); } public Persona(){ this("Sin Nombre"); } //Metodos de la clase. public String getDetalles(){ return "Nombre: " + this.getNombre() + " - Apellido: " + this.getApellido() + " - Edad:" + this.getEdad(); } //Metodos para acceder a la clase. public int getEdad(){ return this.edad; } public boolean setEdad(int nuevaEdad){ if (nuevaEdad > 90) { return false; } else { this.edad = nuevaEdad; return true; } } public String getNombre(){ return this.nombre; } public boolean setNombre(String nuevoNombre){ if (nuevoNombre == "") { return false; } else { this.nombre = nuevoNombre; return true; } }

public String getApellido(){ return this.apellido; } public boolean setApellido(String nuevoApellido){ if (nuevoApellido == "") { return false; } else { this.apellido = nuevoApellido; return true; } } } public class Empleado extends Persona { // Atributos. private int sueldo; private String gerencia; //Metodos Constructores public Empleado(String ger, int sue){ this.setGerencia(ger); this.setSueldo(sue); } public Empleado(String ger){ this(ger,0); } public Empleado(){ this("Sin Gerencia"); } //Metodos de la clase. public String getDetalles(){ return super.getDetalles() + " - Sueldo: " + this.getSueldo() + " - Gerencia: " + this.getGerencia(); } //Metodos para Acceder a los atributos. public int getSueldo(){ return this.sueldo; } public boolean setSueldo(int nuevoSueldo){ if (nuevoSueldo == 0) { return false; } else { this.sueldo = nuevoSueldo; return true; } } public String getGerencia(){ return this.gerencia; } public boolean setGerencia(String nuevaGerencia){ if (nuevaGerencia == "") { return false; }

} }

else { this.gerencia = nuevaGerencia; return true; }

import Persona; import Empleado; public class EjemploHerencia { public static void main(String args[]){ Empleado emp = new Empleado(); System.out.println("Detalles: " + emp.getDetalles()); emp.setNombre("Gustavo"); emp.setApellido("Garcia"); emp.setEdad(27); emp.setGerencia("CRM Masivo"); emp.setSueldo(1000); System.out.println("Detalles: " + emp.getDetalles()); } }

Modulo 3 Manejo de Errores


Excepciones Una clase de tipo Excepcion define las condiciones de error leves que pueda contener el programa. Tambin es posible escribir cdigo que maneje excepciones y haga continuar la ejecucin del programa. Cualquier condicin anormal que pueda trabar la normal ejecucin del programa es un error o una excepcin. Estos pueden ocurrir cuando: El archivo que se est tratando de abrir no existe. La conexin a la red se interrumpe. La clase buscada no se encuentra. Etc. Una clase de tipo Error define condiciones de error serias que no deben ser recuperadas y deben permitir que el programa termine. Java permite que los errores encontrados sean recuperados y utilizados en el programa, de esta forma se pueden manejar. Por ejemplo: public class HolaMundo { public static void main (String args[]) { int i = 0; String greetings [] = { Hola mundo!, No, me equivoque!, HOLA MUNDO!! }; while (i < 4) { System.out.println (greetings [i]); i++; } } }

Al ejecutarse el ciclo por cuarta vez el programa terminar con el siguiente mensaje de error: java.lang.ArrayIndexOutOfBoundsException: 3 at HolaMundo.main (HolaMundo.java:12) El manejo de excepciones permite al programa tomar la excepcin, manejarla y continuar con la ejecucin del mismo. Manejo de Excepciones Instrucciones try y catch Para manejar una excepcin en particular se debe colocar todo el cdigo que la puede producir dentro de la instruccin try, y crear una lista de posibles excepciones para cada tipo de error con catch.

try {

// Cdigo del programa que puede ejecutar alguna excepcin. } catch (MiTipoDeExcepcion e ) { //Cdigo a ejecutarse si MiTipoDeExcepcion es disparada. } catch (Exception e) { // Cdigo a ejecutarse si una excpecin general es disparada. } El mecanismo del llamado por pila: Si hay clases que son llamadas por otras, y generan una excepcin, sta es buscada primero en la clase que la genera, si no la encuentra, busca en la clase que la llam, y as sucesivamente hasta encontrarla, si no la encuentra genera un mensaje de error y termina el programa. Instruccin finally Define un bloque de cdigo que siempre se ejecuta, independientemente de si el programa efectu una excepcin. Ejemplo: try { ComenzarRiego () ; AguaRiego (); } finally { TerminarRiego(); } En el ejemplo anterior TerminarRiego es ejecutada aunque haya existido alguna exceptin mientras ComenzarRiego se ejecutaba. El cdigo dentro de las llaves del try es llamado cdigo protegido. La instruccin finally pudiera no ser ejecutada solo en el caso de que el mtodo System.exit () fuera ejecutado dentro del cdigo protegido, ya que sta deriva la ejecucin normal de programa, terminndolo. Si la instruccin return fuera ejecutada dentro del try, el cdigo de finally sera ejecutado antes de sta. Categoras de Excepciones La clase java.lang.Throwable es la superclase que contiene todos los objetos que pueden utilizar mecanismos de manejo de errores. Las tres clases ms importantes son: Error: Indica un problema severo difcil de recuperar, por ejemplo cuando el programa corre fuera de memoria. RuntimeException: Indica un problema de diseo o implementacin, por ejemplo, ArrayIndexOutOfBoundsException, nunca debera darse si los ndices del array no pasaran el largo del mismo. Exception: Otras excepciones indican dificultades en tiempo de ejecucin que usualmente son causadas por efectos del entorno y pueden ser manejadas. Por ejemplo archivos no encontrados o URL invalida. Excepciones Comunes: Java provee excepciones predefinidas como: ArithmeticException El resultado de dividir por cero una operacin de enteros.

NullPointerException Intentar acceder a algn mtodo o atributo de un objeto sin que ste est instanciado. NegativeArraySizeException Intentar crear un array son un tamao negativo. ArrayIndexOutOfBoundsException Intentar acceder a un elemento del array mayor al tamao del mismo. ScurityException Se suele generar en un browser, la clase SecurityManager genera esa excepcin por applets que intentan : Acceder a una fila local, Abrir un socket en el servidor que no es el mismo que sirve el applet, Ejecutar otro programa en el entorno de ejecucin.

Jerarqua de Excepciones
OutOfMemory Error VirtualMachine Error Error StackOverflow Error

AWTError Arithmetic Excpetion Throwable RuntimeException NullPointer Exception

IndexOutOfBound Exception
Exception

EOFException

IOException FileNotFound Exception

La excepcin Throwable no debe ser usada, en su defecto, se deben utilizar las subclases antes descriptas.

Ejemplo completo: public class HolaMundo { public static void main (String args[]) { int i = 0; String greetings [] = { Hola mundo!, No, me equivoque!, HOLA MUNDO!! }; while (i < 4) { try { System.out.println (greetings [i]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println (Actualice los ndices); I = -1; } finally { System.out.println (Esto siempre se imprime); } i++; } } }

Modulo 4 Applets
Applet Un applet es "una pequea aplicacin accesible en un servidor, que se transporta por la red, se instala automticamente y se ejecuta in situ como parte de un documento web". Es una aplicacin pretendidamente corta basada en un formato grfico sin representacin independiente: es decir, se trata de un elemento a embeber en otras aplicaciones; es un componente en su sentido estricto. Ciclo de vida de un Applet Cuando un applet se carga en el browser, comienza su ciclo de vida, que pasara por las siguientes fases: Se crea una instancia de la clase que controla el applet.. El applet se inicializa. El applet comienza a ejecutarse. El applet empieza a recibir llamadas. Primero recibe una llamada init (inicializar), seguida de un mensaje start (empezar) y paint (pintar). Estas llamadas pueden ser recibidas asincrnicamente. El mtodo init() se llama cada vez que el browser carga por primera vez la clase. Si el applet llamado no lo sobrecarga, init() no hace nada. Fundamentalmente en este mtodo se debe fijar el tamao del applet, aunque en el caso de Netscape el tamao que vale es el que se indique en la lnea del fichero html que cargue el applet. Tambin se deben realizar en este mtodo las cargas de imgenes y sonidos necesarios para la ejecucin del applet. Y, por supuesto, la asignacin de valores a las variables globales a la clase que se utilicen. En el caso de los applet, este mtodo nicamente es llamado por el sistema al cargar el applet. El mtodo start() es la llamada para arrancar el applet cada vez que es visitado. La clase Applet no hace nada en este mtodo. Las clases derivadas deben sobrecargarlo para comenzar la animacin, el sonido, etc. Esta funcin es llamada automticamente cada vez que la zona de visualizacin en que est ubicado el applet se expone a la visin, a fin de optimizar en uso de los recursos del sistema y no ejecutar algo que no puede ser apreciado. Esto es, imaginemos que cargamos un applet en un navegador minimizado; el sistema llamar al mtodo init(), pero no a start(), que s ser llamado cuando restauremos el navegador a un tamao que permita ver el applet. Naturalmente, start() se puede ejecutar varias veces: la primera tras init() y las siguientes (porque init() se ejecuta solamente una vez) tras haber aplicado el mtodo stop(). El mtodo stop() es la llamada para detener la ejecucin del applet. Se llama cuando el applet desaparece de la pantalla. La clase Applet tampoco hace nada en este mtodo, que debera ser sobrecargado por las clases derivadas para detener la animacin, el sonido, etc. Esta funcin es llamada cuando el navegador no incluye en su campo de visin al applet; por ejemplo, cuando abandona la pgina en que est insertado, de forma que el programador puede paralizar las funciones que no resulten necesarias respecto de un applet no visible, y luego recuperar su actividad mediante el mtodo start(). El mtodo destroy() se llama cuando ya no se va a utilizar ms el applet, cuando se necesita que sean liberados todos los recursos dispuestos por el applet, por ejemplo, cuando se cierra el navegador. La clase Applet no hace nada en este mtodo. Las clases derivadas deberan sobrecargarlo para hacer una limpieza final. El mtodo paint ( Graphics g ) es llamado cada vez que el rea de dibujo del applet necesita ser refrescada. La clase Applet simplemente dibuja un rectngulo gris en el rea, es la clase derivada, obviamente, la que debera sobrecargar este mtodo para representar algo inteligente en la pantalla. Cada vez que la zona del applet es cubierta por otra ventana, se desplaza el applet fuera de la visin o el applet cambia de posicin debido a un redimensionamiento del navegador, el sistema llama automticamente a este mtodo, pasando como argumento un objeto de tipo Graphics que delimita la zona a ser pintada; en realidad se

pasa una referencia al contexto grfico en uso, y que representa la ventana del applet en la pgina web. El metodo update( Graphics g ) es el que realmente se llama cuando se necesita una actualizacin de la pantalla. La clase Applet simplemente limpia el rea y llama al mtodo paint(). Esta funcionalidad es suficiente para la mayora de los casos; aunque, de cualquier forma, las clases derivadas pueden sustituir esta funcionalidad para sus propsitos especiales. Llamando al metodo repaint() se podr forzar la actualizacin de un applet. Ejemplo import java.awt.Graphics; import java.applet.Applet; public class HolaMundo extends Applet { public void paint( Graphics g ) { g.drawString( "Hola Curso Java!",25,25 ) ; } } Ejemplo de archivo contenedor Holamundo.html <APPLET>: <APPLET CODE="HolaMundo.class" WIDTH=100 HEIGHT=50> </APPLET> Esta marca html llama al applet HolaMundo.class y establece su ancho y alto inicial. Los atributos obligatorios que acompaan a la etiqueta <APPLET> son: Code: Indica el fichero de clase ejecutable, que tiene la extensin .class. Width: Indica la anchura inicial que el navegador debe reservar para el applet en pixels. Height: Indica la altura inicial en pixels.

Ejemplo completo import java.awt.*; import java.applet.Applet; public class HolaMundo extends Applet { //Atributos de la clase. Font f; //Metodos Constructores. public void init(){ f = new Font("Arial",Font.BOLD,36); } // Sobreescribo Metodos de Applet. public void paint( Graphics screen ) { screen.setFont(f); screen.setColor(Color.red); screen.drawString( "Hola Mundo Applet!",5,40 ) ; } } Holamundo.html <HTML> <HEAD> <TITLE>Hola Mundo version Applet</TITLE> </HEAD> <BODY> <APPLET> <APPLET CODE="HolaMundo.class" WIDTH=600 HEIGHT=100> </APPLET> </BODY> </HTML>

Modulo 5 Desarrollo de Aplicaciones Graficas


Introduccin al AWT AWT es el acrnimo de Abstract Window Toolkit.Se trata de una biblioteca de clases Java para el desarrollo de Interfaces de Usuario Grficas. La estructura bsica del AWT se basa en Componentes y Contenedores. Estos ltimos contienen Componentes posicionados a su respecto y son Componentes a su vez, de forma que los eventos pueden tratarse tanto en Contenedores como en Componentes, corriendo por cuenta del programador el encaje de todas las piezas, as como la seguridad de tratamiento de los eventos adecuados. Debido a que el lenguaje de programacin Java es independiente de la plataforma en que se ejecuten sus aplicaciones, el AWT tambin es independiente de la plataforma en que se ejecute. El AWT proporciona un conjunto de herramientas para la construccin de interfaces grficas que tienen una apariencia y se comportan de forma semejante en todas las plataformas en que se ejecute. Los elementos de interface proporcionados por el AWT estn implementados utilizando toolkits nativos de las plataformas, preservando una apariencia semejante a todas las aplicaciones que se creen para esa plataforma. La estructura de la versin actual del AWT podemos resumirla en los puntos que exponemos a continuacin: Los Contenedores contienen Componentes, que son los controles bsicos No se usan posiciones fijas de los Componentes, sino que estn situados a travs de una disposicin controlada (layouts) El comn denominador de ms bajo nivel se acerca al teclado, ratn y manejo de eventos Alto nivel de abstraccin respecto al entorno de ventanas en que se ejecute la aplicacin (no hay reas cliente, ni llamadas a X, ni hWnds, etc.) La arquitectura de la aplicacin es dependiente del entorno de ventanas, en vez de tener un tamao fijo Componentes y Contenedores Una interface grfica est construida en base a elementos grficos bsicos, los componentes. Tpicos ejemplos de estos Componentes son los botones, barras de desplazamiento, etiquetas, listas, cajas de seleccin o campos de texto. Los Componentes permiten al usuario interactuar con la aplicacin y proporcionar informacin desde el programa al usuario sobre el estado del programa. En el AWT, todos los Componentes de la interface de usuario son instancias de la clase Component o uno de sus subtipos. Los Componentes no se encuentran aislados, sino agrupados dentro de Contenedores. Los Contenedores contienen y organizan la situacin de los Componentes; adems, los Contenedores son en s mismos Componentes y como tales pueden ser situados dentro de otros Contenedores. Tambin contienen el cdigo necesario para el control de eventos, cambiar la forma del cursor o modificar el icono de la aplicacin. En el AWT, todos los Contenedores son instancias de la clase Container o uno de sus subtipos.

Los Componentes deben circunscribirse dentro del Contenedor que los contiene. Esto hace que el anidamiento de Componentes (incluyendo Contenedores) en Contenedores crean rboles de elementos, comenzando con un Contenedor en la raiz del rbol y expandindolo en sus ramas. A continuacin presentamos el rbol que representa la interface que corresponde con la aplicacin grfica generada anteriormente.

PANELES La clase Panel es el ms simple de los Contenedores de Componentes grficos. En realidad, se trataba de crear una clase no-abstracta (Container s lo es) que sirviera de base a los applet y a otras pequeas aplicaciones. La clase Panel consta de dos mtodos propios: el constructor, cuyo fin es crear un nuevo Panel con un LayoutManager de tipo FlowLayout (el de defecto), y el mtodo addNotify() que, sobrecargando la funcin del mismo nombre en la clase Container, llama al mtodo createPanel() del Toolkit adecuado, creando as un PanelPeer. El AWT enviar as al Panel (y por tanto al applet) todos los eventos que sobre l ocurran. Esto que puede parecer un poco rebuscado, obedece al esquema arquitectnico del AWT; se trata del bien conocido esquema de separacin interface/implementacin que establece por un lado una clase de interface y por otro distintas clases de implementacin para cada una de las plataformas elegidas. El uso de Paneles permite que las aplicaciones puedan utilizar mltiples layouts, es decir, que la disposicin de los componentes sobre la ventana de visualizacin pueda modificarse con mucha flexibilidad. Permite que cada Contenedor pueda tener su propio esquema de fuentes de caracteres, color de fondo, zona de dilogo, etc. herramientas y a la barra de estado con new; al contrario que en C++, en Java todos los objetos deben ser creados con el operador new: add( "North",tb = new ToolBar() ); add( "South",sb = new StatusBar() ); Tambin vamos a incorporar un nuevo evento a nuestro controlador, para que maneje los eventos de tipo ACTION_EVENT que le llegarn cuando se pulsen los botones de la barra de herramientas o se realice alguna seleccin, etc. case Event.ACTION_EVENT:

{ be.verEstado( evt.arg.toString() ); return true; } Cuando la aplicacin reciba este tipo de evento, alterar el contenido de la barra de estado para mostrar la informacin de la seleccin realizada o el botn pulsado.

Al final, la apariencia de la aplicacin en pantalla es la que presenta la figura anterior. LAYOUTS Los layout managers o manejadores de composicin, en traduccin literal, ayudan a adaptar los diversos Componentes que se desean incorporar a un Panel, es decir, especifican la apariencia que tendrn los Componentes a la hora de colocarlos sobre un Contenedor. Java dispone de varios, en la actual versin, tal como se muestra en la imagen:

Por qu Java proporciona estos esquemas predefinidos de disposicin de componentes? La razn es simple: imaginemos que deseamos agrupar objetos de distinto tamao en celdas de una rejilla virtual: si confiados en nuestro conocimiento de un sistema grfico determinado, codificamos a mano tal disposicin, deberemos preveer el redimensionamiento del applet, su repintado cuando sea cubierto por otra ventana, etc., adems de todas las cuestiones relacionadas con un posible cambio de plataforma (uno nunca sabe a donde van a ir a parar los propios hijos, o los applets).

Modulo 6 MultiProgramacion
Considerando el entorno multithread, cada thread (hilo, flujo de control del programa) representa un proceso individual ejecutndose en un sistema. A veces se les llama procesos ligeros o contextos de ejecucin. Tpicamente, cada thread controla un nico aspecto dentro de un programa, como puede ser supervisar la entrada en un determinado perifrico o controlar toda la entrada/salida del disco. Todos los threads comparten los mismos recursos, al contrario que los procesos en donde cada uno tiene su propia copia de cdigo y datos (separados unos de otros). Grficamente, los threads se parecen en su funcionamiento a lo que muestra la figura siguiente:

Flujo de Programas Programas de flujo nico Un programa de flujo nico o mono-hilvanado (single-thread) utiliza un nico flujo de control (thread) para controlar su ejecucin. Muchos programas no necesitan la potencia o utilidad de mltiples flujos de control. Sin necesidad de especificar explcitamente que se quiere un nico flujo de control, muchos de los applets y aplicaciones son de flujo nico. Por ejemplo, en nuestra aplicacin estndar de saludo: public class HolaMundo { static public void main( String args[] ) { System.out.println( "Hola Mundo!" ); } } Aqu, cuando se llama a main(), la aplicacin imprime el mensaje y termina. Esto ocurre dentro de un nico thread. Programas de flujo mltiple En nuestra aplicacin de saludo, no vemos el thread que ejecuta nuestro programa. Sin embargo, Java posibilita la creacin y control de threads explcitamente. La utilizacin de threads en Java, permite una enorme flexibilidad a los programadores a la hora de plantearse el desarrollo de aplicaciones. La simplicidad para crear, configurar y ejecutar threads, permite que se puedan implementar muy poderosas y portables aplicaciones/applets que no se puede con otros lenguajes de tercera generacin. En un lenguaje orientado a Internet como es Java, esta herramienta es vital. Si se ha utilizado un navegador con soporte Java, ya se habr visto el uso de mltiples threads en Java. Habr observado que dos applet se pueden ejecutar al mismo tiempo, o que puede desplazar la pgina del navegador mientras el applet contina ejecutndose. Esto no significa que el applet utilice mltiples threads, sino que el navegador es multithreaded. Las aplicaciones (y applets) multithreaded utilizan muchos contextos de ejecucin para cumplir su trabajo. Hacen uso del hecho de que muchas tareas contienen subtareas distintas e independientes. Se puede utilizar un thread para cada subtarea. Mientras que los programas de flujo nico pueden realizar su tarea ejecutando las subtareas secuencialmente, un programa multithreaded permite que cada thread comience y termine tan pronto como sea posible. Este comportamiento presenta una mejor respuesta a la entrada en tiempo real.

Ejemplo de Hola Mundo version Threads public class MyThread extends Thread { private int intervalo; private String descripcion; public void setIntervalo(int nuevointervalo){ intervalo = nuevointervalo; } public int getIntervalo(){ return intervalo; } public void setDescripcion(String nuevadescripcion){ descripcion = nuevadescripcion; } public String getDescripcion(){ return descripcion; } public MyThread(String nuevadescripcion){ this.setDescripcion(nuevadescripcion); } public void run(){ while(true){ try { this.setIntervalo((int)(Math.random()*1000)); this.sleep(this.getIntervalo()); System.out.println("Descripcion: " + this.getDescripcion() + " - Intervalo:" + this.getIntervalo()); } catch (Exception e) { System.out.println("Error en Tbread"); } } } } import MyThread; public class TesterMyThread { public static void try { MyThread th1 MyThread th2 MyThread th3 th1.start(); th2.start(); th3.start(); } catch (Exception e) { System.out.println("Error en Main"); } } } main (String args[]){ = new MyThread("Hola Mundo - Thread 1"); = new MyThread("Hola Mundo - Thread 2"); = new MyThread("Hola Mundo - Thread 3");

CREACION Y CONTROL DE THREADS Creacin de un Thread Hay dos modos de conseguir threads en Java. Una es implementando la interface Runnable, la otra es extender la clase Thread. La implementacin de la interface Runnable es la forma habitual de crear threads. Las interfaces proporcionan al programador una forma de agrupar el trabajo de infraestructura de una clase. Se utilizan para disear los requerimientos comunes al conjunto de clases a implementar. La interface define el trabajo y la clase, o clases, que implementan la interface realizan ese trabajo. Los diferentes grupos de clases que implementen la interface tendrn que seguir las mismas reglas de funcionamiento. Hay una cuantas diferencias entre interface y clase. Primero, una interface solamente puede contener mtodos abstractos y/o variables estticas y finales (constantes). Las clases, por otro lado, pueden implementar mtodos y contener variables que no sean constantes. Segundo, una interface no puede implementar cualquier mtodo. Una clase que implemente una interface debe implementar todos los mtodos definidos en esa interface. Una interface tiene la posibilidad de poder extenderse de otras interfaces y, al contrario que las clases, puede extenderse de mltiples interfaces. Adems, una interface no puede ser instanciada con el operador new; por ejemplo, la siguiente sentencia no est permitida: Runnable a = new Runnable(); // No se permite El primer mtodo de crear un thread es simplemente extender la clase Thread: class MiThread extends Thread { public void run() { ... } El ejemplo anterior crea una nueva clase MiThread que extiende la clase Thread y sobrecarga el mtodo Thread.run() por su propia implementacin. El mtodo run() es donde se realizar todo el trabajo de la clase. Extendiendo la clase Thread, se pueden heredar los mtodos y variables de la clase padre. En este caso, solamente se puede extender o derivar una vez de la clase padre. Esta limitacin de Java puede ser superada a travs de la implementacin de Runnable: public class MiThread implements Runnable { Thread t; public void run() { // Ejecucin del thread una vez creado } } En este caso necesitamos crear una instancia de Thread antes de que el sistema pueda ejecutar el proceso como un thread. Adems, el mtodo abstracto run() est definido en la interface Runnable tiene que ser implementado. La nica diferencia entre los dos mtodos es que este ltimo es mucho ms flexible. En el ejemplo anterior, todava tenemos oportunidad de extender la clase MiThread, si fuese necesario. La mayora de las clases creadas que necesiten ejecutarse como un thread , implementarn la interface Runnable, ya que probablemente extendern alguna de su funcionalidad a otras clases. No pensar que la interface Runnable est haciendo alguna cosa cuando la tarea se est ejecutando. Solamente contiene mtodos abstractos, con lo cual es una clase para dar idea sobre el diseo de la clase Thread. De hecho, si vemos los fuentes de Java, podremos comprobar que solamente contiene un mtodo abstracto: package java.lang; public interface Runnable { public abstract void run() ; } Y esto es todo lo que hay sobre la interface Runnable. Como se ve, una interface slo proporciona un diseo para las clases que vayan a ser implementadas. En el caso de Runnable, fuerza a la definicin del mtodo run(), por lo tanto, la mayor parte del trabajo se hace en la clase Thread. Un vistazo un poco ms profundo a la definicin de la clase Thread nos da idea de lo que realmente est pasando: public class Thread implements Runnable { ... public void run() {

if( tarea != null ) tarea.run() ; } } ... } De este trocito de cdigo se desprende que la clase Thread tambin implemente la interface Runnable. tarea.run() se asegura de que la clase con que trabaja (la clase que va a ejecutarse como un thread) no sea nula y ejecuta el mtodo run() de esa clase. Cuando esto suceda, el mtodo run() de la clase har que corra como un thread. Arranque de un Thread Las aplicaciones ejecutan main() tras arrancar. Esta es la razn de que main() sea el lugar natural para crear y arrancar otros threads. La lnea de cdigo: t1 = new TestTh( "Thread 1",(int)(Math.random()*2000) ); crea un nuevo thread. Los dos argumentos pasados representan el nombre del thread y el tiempo que queremos que espere antes de imprimir el mensaje. Al tener control directo sobre los threads, tenemos que arrancarlos explcitamente. En nuestro ejemplo con: t1.start(); start(), en realidad es un mtodo oculto en el thread que llama al mtodo run(). Manipulacin de un Thread Si todo fue bien en la creacin del thread, t1 debera contener un thread vlido, que controlaremos en el mtodo run(). Una vez dentro de run(), podemos comenzar las sentencias de ejecucin como en otros programas. run() sirve como rutina main() para los threads; cuando run() termina, tambin lo hace el thread. Todo lo que queramos que haga el thread ha de estar dentro de run(), por eso cuando decimos que un mtodo es Runnable, nos obliga a escribir un mtodo run(). En este ejemplo, intentamos inmediatamente esperar durante una cantidad de tiempo aleatoria (pasada a travs del constructor): sleep( retardo ); El mtodo sleep() simplemente le dice al thread que duerma durante los milisegundos especificados. Se debera utilizar sleep() cuando se pretenda retrasar la ejecucin del thread. sleep() no consume recursos del sistema mientras el thread duerme. De esta forma otros threads pueden seguir funcionando. Una vez hecho el retardo, se imprime el mensaje "Hola Mundo!" con el nombre del thread y el retardo. Suspensin de un Thread Puede resultar til suspender la ejecucin de un thread sin marcar un lmite de tiempo. Si, por ejemplo, est construyendo un applet con un thread de animacin, querr permitir al usuario la opcin de detener la animacin hasta que quiera continuar. No se trata de terminar la animacin, sino desactivarla. Para este tipo de control de thread se puede utilizar el mtodo suspend(). t1.suspend(); Este mtodo no detiene la ejecucin permanentemente. El thread es suspendido indefinidamente y para volver a activarlo de nuevo necesitamos realizar una invocacin al mtodo resume(): t1.resume(); Parada de un Thread El ltimo elemento de control que se necesita sobre threads es el mtodo stop(). Se utiliza para terminar la ejecucin de un thread: t1.stop(); Esta llamada no destruye el thread, sino que detiene su ejecucin. La ejecucin no se puede reanudar ya con t1.start(). Cuando se desasignen las variables que se usan en el thread, el objeto thread (creado con new) quedar marcado para eliminarlo y el garbage collector se encargar de liberar la memoria que utilizaba. En nuestro ejemplo, no necesitamos detener explcitamente el thread. Simplemente se le deja terminar. Los programas ms complejos necesitarn un control sobre cada uno de los threads que lancen, el mtodo stop() puede utilizarse en esas situaciones. Si se necesita, se puede comprobar si un thread est vivo o no; considerando vivo un thread que ha comenzado y no ha sido detenido. t1.isAlive();

Este mtodo devolver true en caso de que el thread t1 est vivo, es decir, ya se haya llamado a su mtodo run() y no haya sido parado con un stop() ni haya terminado el mtodo run() en su ejecucin. ARRANCAR Y PARAR THREADS Ahora que ya hemos visto por encima como se arrancan, paran y manipulan threads, vamos a mostrar un ejemplo un poco ms grfico, se trata de un contador, cuyo cdigo (App1Thread.java) es el siguiente: import java.awt.*; import java.applet.Applet; public class App1Thread extends Applet implements Runnable { Thread t; int contador; public void init() { contador = 0; t = new Thread( this ); t.start(); } public void run() { while( true ) { contador++; repaint(); try { t.sleep( 10 ); } catch( InterruptedException e ) { ; }; } } public boolean mouseDown( Event evt,int x,int y ) { t.stop(); return( true ); } public void paint( Graphics g ) { g.drawString( Integer.toString( contador ),10,10 ); System.out.println( "Contador = "+contador ); } public void stop() { t.stop(); } } Este applet arranca un contador en 0 y lo incrementa, presentando su salida tanto en la pantalla grfica como en la consola. Una primera ojeada al cdigo puede dar la impresin de que el programa empezar a contar y presentar cada nmero, pero no es as. Una revisin ms profunda del flujo de ejecucin del applet, nos revelar su verdadera identidad. En este caso, la clase App1Thread est forzada a implementar Runnable sobre la clase Applet que extiende. Como en todos los applets, el mtodo init() es el primero que se ejecuta. En init(), la variable contador se inicializa a cero y se crea una nueva instancia de la clase Thread. Pasndole this al constructor de Thread, el nuevo thread ya conocer al objeto que va a correr. En este caso this es una referencia a App1Thread. Despus de que hayamos creado el thread, necesitamos arrancarlo. La llamada a start(), llamar a su vez al mtodo run() de nuestra clase, es decir, a App1Thread.run(). La llamada a start() retornar con xito y el thread comenzar a ejecutarse en ese instante. Observar que el mtodo run() es un bucle infinito. Es

infinito porque una vez que se sale de l, la ejecucin del thread se detiene. En este mtodo se incrementar la variable contador, se duerme 10 milisegundos y enva una peticin de refresco del nuevo valor al applet. Es muy importante dormirse en algn lugar del thread, porque sino, el thread consumir todo el tiempo de la CPU para su proceso y no permitir que entren otros mtodos de otros threads a ejecutarse. Otra forma de detener la ejecucin del thread es hacer una llamada al mtodo stop(). En el contador, el thread se detiene cuando se pulsa el ratn mientras el cursor se encuentre sobre el applet. Dependiendo de la velocidad del ordenador, se presentarn los nmeros consecutivos o no, porque el incremento de la variable contador es independiente del refresco en pantalla. El applet no se refresca a cada peticin que se le hace, sino que el sistema operativo encolar las peticiones y las que sean sucesivas las convertirn en un nico refresco. As, mientras los refescos se van encolando, la variable contador se estar todava incrementando, pero no se visualiza en pantalla. SUSPENDER Y REANUDAR THREADS Una vez que se para un thread, ya no se puede rearrancar con el comando start(), debido a que stop() concluir la ejecucin del thread. Por ello, en ver de parar el thread, lo que podemos hacer es dormirlo, llamando al mtodo sleep(). El thread estar suspendido un cierto tiempo y luego reanudar su ejecucin cuando el lmite fijado se alcance. Pero esto no es til cuando se necesite que el thread reanude su ejecucin ante la presencia de ciertos eventos. En estos casos, el mtodo suspend() permite que cese la ejecucin del thread y el mtodo resume() permite que un mtodo suspendido reanude su ejecucin. En la siguiente versin de nuestra clase contador, App2Thread.java, modificamos el applet para que utilice los mtodos suspend() y resume(): public class App2Thread extends Applet implements Runnable { Thread t; int contador; boolean suspendido; ... public boolean mouseDown( Event evt,int x,int y ) { if( suspendido ) t.resume(); else t.suspend(); suspendido = !suspendido; return( true ); } ... Para controlar el estado del applet, hemos introducido la variable suspendido. Diferenciar los distintos estados de ejecucin del applet es importante porque algunos mtodos pueden generar excepciones si se llaman desde un estado errneo. Por ejemplo, si el applet ha sido arrancado y se detiene con stop(), si se intenta ejecutar el mtodo start(), se generar una excepcin IllegalThreadStateException.

ESTADOS DE UN THREAD Durante el ciclo de vida de un thread, ste se puede encontrar en diferentes estados. La figura siguiente muestra estos estados y los mtodos que provocan el paso de un estado a otro. Este diagrama no es una mquina de estados finita, pero es lo que ms se aproxima al funcionamiento real de un thread .

Modulo 7 Comunicaciones
Todos los lenguajes de programacin tienen alguna forma de interactuar con los sistemas de ficheros locales; Java no es una excepcin. Cuando se desarrollan applets para utilizar en red, hay que tener en cuenta que la entrada/salida directa a fichero es una violacin de seguridad de acceso. Muchos usuarios configurarn sus navegadores para permitir el acceso al sistema de ficheros, pero otros no. Por otro lado, si se est desarrollando una aplicacin Java para uso interno, probablemente ser necesario el acceso directo a ficheros. Ficheros Antes de realizar acciones sobre un fichero, necesitamos un poco de informacin sobre ese fichero. La clase File proporciona muchas utilidades relacionadas con ficheros y con la obtencin de informacin bsica sobre esos ficheros. Creacin de un objeto File Para crear un objeto File nuevo, se puede utilizar cualquiera de los tres constructores siguientes: File miFichero; miFichero = new File( "/etc/kk" ); o miFichero = new File( "/etc","kk" ); o File miDirectorio = new File( "/etc" ); miFichero = new File( miDirectorio,"kk" ); El constructor utilizado depende a menudo de otros objetos File necesarios para el acceso. Por ejemplo, si slo se utiliza un fichero en la aplicacin, el primer constructor es el mejor. Si en cambio, se utilizan muchos ficheros desde un mismo directorio, el segundo o tercer constructor sern ms cmodos. Y si el directorio o el fichero es una variable, el segundo constructor ser el ms til. Comprobaciones y Utilidades Una vez creado un objeto File, se puede utilizar uno de los siguientes mtodos para reunir informacin sobre el fichero: Nombres de fichero String getName() String getPath() String getAbsolutePath() String getParent() boolean renameTo( File nuevoNombre ) Comprobaciones boolean exists() boolean canWrite() boolean canRead() boolean isFile() boolean isDirectory() boolean isAbsolute() Informacin general del fichero long lastModified() long length() Utilidades de directorio boolean mkdir() String[] list() Vamos a desarrollar una pequea aplicacin que muestra informacin sobre los ficheros pasados como argumentos en la lnea de comandos, InfoFichero.java: import java.io.*; class InfoFichero { public static void main( String args[] ) throws IOException { if( args.length > 0 ) {

for( int i=0; i < args.length; i++ ) { File f = new File( args[i] ); System.out.println( "Nombre: "+f.getName() ); System.out.println( "Camino: "+f.getPath() ); if( f.exists() ) { System.out.print( "Fichero existente " ); System.out.print( (f.canRead() ? " y se puede Leer" : "" ) ); System.out.print( (f.canWrite() ? " y se puese Escribir" : "" ) ); System.out.println( "." ); System.out.println( "La longitud del fichero son "+ f.length()+" bytes" ); } else System.out.println( "El fichero no existe." ); } } else System.out.println( "Debe indicar un fichero." ); } } STREAMS DE ENTRADA Hay muchas clases dedicadas a la obtencin de entrada desde un fichero. Este es el esquema de la jerarqua de clases de entrada por fichero:

Objetos FileInputStream Los objetos FileInputStream tpicamente representan ficheros de texto accedidos en orden secuencial, byte a byte. Con FileInputStream, se puede elegir acceder a un byte, varios bytes o al fichero completo. Apertura de un FileInputStream Para abrir un FileInputStream sobre un fichero, se le da al constructor un String o un objeto File: FileInputStream mi FicheroSt; miFicheroSt = new FileInputStream( "/etc/kk" ); Tambin se puede utilizar: File miFichero FileInputStream miFicheroSt; miFichero = new File( "/etc/kk" ); miFicheroSt = new FileInputStream( miFichero ); Lectura de un FileInputStream Una vez abierto el FileInputStream, se puede leer de l. El mtodo read() tiene muchas opciones:

int read(); Lee un byte y devuelve -1 al final del stream. int read( byte b[] ); Llena todo el array, si es posible. Devuelve el nmero de bytes ledos o -1 si se alcanz el final del stream. int read( byte b[],int offset,int longitud ); Lee longitud bytes en b comenzando por b[offset]. Devuelve el nmero de bytes ledos o -1 si se alcanz el final del stream. Cierre de FileInputStream Cuando se termina con un fichero, existen dos opciones para cerrarlo: explcitamente, o implcitamente cuando se recicla el objeto (el garbage collector se encarga de ello). Para cerrarlo explcitamente, se utiliza el mtodo close(): miFicheroSt.close(); Ejemplo: Visualizacin de un fichero Si la configuracin de la seguridad de Java permite el acceso a ficheros, se puede ver el contenido de un fichero en un objeto TextArea. El cdigo siguiente contiene los elementos necesarios para mostrar un fichero: FileInputStream fis; TextArea ta; public void init() { byte b[] = new byte[1024]; int i; // El buffer de lectura se debe hacer lo suficientemente grande // o esperar a saber el tamao del fichero String s; try { fis = new FileInputStream( "/etc/kk" ); } catch( FileNotFoundException e ) { /* Hacer algo */ } try { i = fis.read( b ); } catch( IOException e ) { /* Hacer algo */ } s = new String( b,0 ); ta = new TextArea( s,5,40 ); add( ta ); } Hemos desarrollado un ejemplo, Agenda.java, en el que partimos de un fichero agenda que dispone de los datos que nosotros deseamos de nuestros amigos, como son: nombre, telfono y direccin. Si tecleamos un nombre, buscar en el fichero de datos si existe ese nombre y presentar la informacin que se haya introducido. Para probar, intentar que aparezca la informacin de Pepe. Objetos DataInputStream Los objetos DataInputStream se comportan como los FileInputStream. Los streams de datos pueden leer cualquiera de las variables de tipo nativo, como floats, ints o chars. Generalmente se utilizan DataInputStream con ficheros binarios. Apertura y cierre de DataInputStream Para abrir y cerrar un objeto DataInputStream, se utilizan los mismos mtodos que para FileInputStream: DataInputStream miDStream; FileInputStream miFStream; // Obtiene un controlador de fichero

miFStream = new FileInputStream "/etc/ejemplo.dbf" ); //Encadena un fichero de entrada de datos miDStream = new DataInputStream( miFStream ); // Ahora se pueden utilizar los dos streams de entrada para // acceder al fichero (si se quiere...) miFStream.read( b ); i = miDStream.readInt(); // Cierra el fichero de datos explcitamente //Siempre se cierra primero el fichero stream de mayor nivel miDStream.close(); miFStream.close(); Lectura de un DataInputStream Al acceder a un fichero como DataInputStream, se pueden utilizar los mismos mtodos read() de los objetos FileInputStream. No obstante, tambin se tiene acceso a otros mtodos diseados para leer cada uno de los tipos de datos: byte readByte() int readUnsignedByte() short readShort() int readUnsignedShort() char readChar() int readInt() long readLong() float readFloat() double readDouble() String readLine() Cada mtodo leer un objeto del tipo pedido. Para el mtodo String readLine(), se marca el final de la cadena con \n, \r, \r\n o con EOF. Para leer un long, por ejemplo: long numeroSerie; ... numeroSerie = miDStream.readLong(); Streams de entrada de URLs Adems del acceso a ficheros, Java proporciona la posibilidad de acceder a URLs como una forma de acceder a objetos a travs de la red. Se utiliza implcitamente un objeto URL al acceder a sonidos e imgenes, con el mtodo getDocumentBase() en los applets: String imagenFich = new String( "imagenes/pepe.gif" ); imagenes[0] = getImage( getDocumentBase(),imagenFich ); No obstante, se puede proporcionar directamente un URL, si se quiere: URL imagenSrc; imagenSrc = new URL( "http://enterprise.com/~info" ); imagenes[0] = getImage( imagenSrc,"imagenes/pepe.gif" ); Apertura de un Stream de entrada de URL Tambin se puede abrir un stream de entrada a partir de un URL. Por ejemplo, se puede utilizar un fichero de datos para un applet: ImputStream is; byte buffer[] = new byte[24]; is = new URL( getDocumentBase(),datos).openStream(); Ahora se puede utilizar is para leer informacin de la misma forma que se hace con un objeto FileInputStream: is.read( buffer,0,buffer.length ); NOTA: Debe tenerse muy en cuenta que algunos usuarios pueden haber configurado la seguridad de sus navegadores para que los applets no accedan a ficheros. STREAMS DE SALIDA La contrapartida necesaria de la lectura de datos es la escritura de datos. Como con los Streams de entrada, las clases de salida estn ordenadas jerrquicamente:

Examinaremos las clases FileOutputStream y DataOutputStream para complementar los streams de entrada que se han visto. En los ficheros fuente del directorio $JAVA_HOME/src/java/io se puede ver el uso y mtodos de estas clases, as como de los streams de entrada ($JAVA_HOME es el directorio donde se haya instalado el Java Development Kit, en sistemas UNIX). Objetos FileOutputStream Los objetos FileOutputStream son tiles para la escritura de ficheros de texto. Como con los ficheros de entrada, primero se necesita abrir el fichero para luego escribir en l. Apertura de un FileOutputStream Para abrir un objeto FileOutputStream, se tienen las mismas posibilidades que para abrir un fichero stream de entrada. Se le da al constructor un String o un objeto File. FileOutputStream miFicheroSt; miFicheroSt = new FileOutputStream( "/etc/kk" ); Como con los streams de entrada, tambin se puede utilizar: File miFichero FileOutputStream miFicheroSt; miFichero = new File( "/etc/kk" ); miFicheroSt = new FileOutputStream( miFichero ); Escritura en un FileOutputStream Una vez abierto el fichero, se pueden escribir bytes de datos utilizando el mtodo write(). Como con el mtodo read() de los streams de entrada, tenemos tres posibilidades: void write( int b ); Escribe un byte. void write( byte b[] ); Escribe todo el array, si es posible. void write( byte b[],int offset,int longitud ); Escribe longitud bytes en b comenzando por b[offset]. Cierre de FileOutputStream Cerrar un stream de salida es similar a cerrar streams de entrada. Se puede utilizar el mtodo explcito: miFicheroSt.close(); O, se puede dejar que el sistema cierre el fichero cuando se recicle miFicheroSt. Ejemplo: Almacenamiento de Informacin Este programa, Telefonos.java, pregunta al usuario una lista de nombres y nmeros de telfono. Cada nombre y nmero se aade a un fichero situado en una localizacin fija. Para indicar que se ha introducido toda la lista, el usuario especifica "Fin" ante la solicitud de entrada del nombre. Una vez que el usuario ha terminado de teclear la lista, el programa crear un fichero de salida que se mostrar en pantalla o se imprimir. Por ejemplo: 95-4751232,Juanito 564878,Luisa 123456,Pepe 347698,Antonio 91-3547621,Maria El cdigo fuente del programa es el siguiente: import java.io.*; class Telefonos { static FileOutputStream fos; public static final int longLinea = 81; public static void main( String args[] ) throws IOException {

byte tfno[] = new byte[longLinea]; byte nombre[] = new byte[longLinea]; fos = new FileOutputStream( "telefono.dat" ); while( true ) { System.err.println( "Teclee un nombre ('Fin' termina)" ); leeLinea( nombre ); if( "fin".equalsIgnoreCase( new String( nombre,0,0,3 ) ) ) break; System.err.println( "Teclee el numero de telefono" ); leeLinea( tfno ); for( int i=0; tfno[i] != 0; i++ ) fos.write( tfno[i] ); fos.write( ',' ); for( int i=0; nombre[i] != 0; i++ ) fos.write( nombre[i] ); fos.write( '\n' ); } fos.close(); } private static void leeLinea( byte linea[] ) throws IOException { int b = 0; int i = 0; while( (i < ( longLinea-1) ) && ( ( b = System.in.read() ) != '\n' ) ) linea[i++] = (byte)b; linea[i] = (byte)0; } } Streams de salida con buffer Si se trabaja con gran cantidad de datos, o se escriben muchos elementos pequeos, ser una buena idea utilizar un stream de salida con buffer. Los streams con buffer ofrecen los mismos mtodos de la clase FileOutputStream, pero toda salida se almacena en un buffer. Cuando se llena el buffer, se enva a disco con una nica operacin de escritura; o, en caso necesario, se puede enviar el buffer a disco en cualquier momento. Creacin de Streams de salida con buffer Para crear un stream BufferedOutput, primero se necesita un stream FileOutput normal; entonces se le aade un buffer al stream: FileOutputStream miFileStream; BufferdOutpurStream miBufferStream; // Obtiene un controlador de fichero miFileStream = new FileOutputStream( "/tmp/kk" ); // Encadena un stream de salida con buffer miBufferStream = new BufferedOutputStream( miFileStream ); Volcado y Cierre de Streams de salida con buffer Al contrario que los streams FileOutput, cada escritura al buffer no se corresponde con una escritura en disco. A menos que se llene el buffer antes de que termine el programa, cuando se quiera volcar el buffer explcitamente se debe hacer mediante una llamada a flush(): // Se fuerza el volcado del buffer a disco miBufferStream.flush(); // Cerramos el fichero de datos. Siempre se ha de cerrar primero el // fichero stream de mayor nivel miBufferStream.close(); miFileStream.close(); Streams DataOutput

Java tambin implementa una clase de salida complementaria a la clase DataInputStream. Con la clase DataOutputStream, se pueden escribir datos binarios en un fichero. Apertura y cierre de objetos DataOutputStream Para abrir y cerrar objetos DataOutputStream, se utilizan los mismos mtodos que para los objetos FileOutputStream: DataOutputStream miDataStream; FileOutputStream miFileStream; BufferedOutputStream miBufferStream; // Obtiene un controlador de fichero miFileStream = new FileOutputStream( "/tmp/kk" ); // Encadena un stream de salida con buffer (por eficiencia) miBufferStream = new BufferedOutputStream( miFileStream ); // Encadena un fichero de salida de datos miDataStream = new DataOutputStream( miBufferStream ); // Ahora se pueden utilizar los dos streams de entrada para // acceder al fichero (si se quiere) miBufferStream.write( b ); miDataStream.writeInt( i ); // Cierra el fichero de datos explcitamente. Siempre se cierra // primero el fichero stream de mayor nivel miDataStream.close(); miBufferStream.close(); miFileStream.close(); Escritura en un objeto DataOutputStream Cada uno de los mtodos write() accesibles por los FileOutputStream tambin lo son a travs de los DataOutputStream. Tambin encontrar mtodos complementarios a los de DataInputStream: void writeBoolean( boolean b ); void writeByte( int i ); void writeShort( int i ); void writeChar( int i ); void writeInt( int i ); void writeFloat( float f ); void writeDouble( double d ); void writeBytes( String s ); void writeChars( string s ); Para las cadenas, se tienen dos posibilidades: bytes y caracteres. Hay que recordar que los bytes son objetos de 8 bits y los caracteres lo son de 16 bits. Si nuestras cadenas utilizan caracteres Unicode, debemos escribirlas con writeChars(). Contabilidad de la salida Otra funcin necesaria durante la salida es el mtodo size(). Este mtodo simplemente devuelve el nmero total de bytes escritos en el fichero. Se puede utilizar size() para ajustar el tamao de un fichero a mltiplo de cuatro. Por ejemplo, de la forma siguiente: ... int numBytes = miDataStream.size() % 4; for( int i=0; i < numBytes; i++ ) miDataStream.write( 0 ); ...

En este captulo no nos vamos a extender demasiado en profundidades sobre la comunicacin y funcionamiento de redes, aunque s proporcionaremos un breve bao inicial para sentar, o recordar, los fundamentos de la comunicacin en red, tomando como base Unix.

Presentaremos un ejemplo bsico de cliente/servidor sobre sockets TCP/IP, proporcionando un punto de partida para el desarrollo de otras aplicaciones cliente/servidor basadas en sockets, que posteriormente implementaremos. SOCKETS Los sockets son puntos finales de enlaces de comunicaciones entre procesos. Los procesos los tratan como descriptores de ficheros, de forma que se pueden intercambiar datos con otros procesos transmitiendo y recibiendo a travs de sockets. El tipo de sockets describe la forma en la que se transfiere informacin a travs de ese socket. Sockets Stream (TCP, Transport Control Protocol) Son un servicio orientado a conexin donde los datos se transfieren sin encuadrarlos en registros o bloques. Si se rompe la conexin entre los procesos, stos sern informados. El protocolo de comunicaciones con streams es un protocolo orientado a conexin, ya que para establecer una comunicacin utilizando el protocolo TCP, hay que establecer en primer lugar una conexin entre un par de sockets. Mientras uno de los sockets atiende peticiones de conexin (servidor), el otro solicita una conexin (cliente). Una vez que los dos sockets estn conectados, se pueden utilizar para transmitir datos en ambas direcciones. Sockets Datagrama (UDP, User Datagram Protocol) Son un servicio de transporte sin conexin. Son ms eficientes que TCP, pero no est garantizada la fiabilidad. Los datos se envan y reciben en paquetes, cuya entrega no est garantizada. Los paquetes pueden ser duplicados, perdidos o llegar en un orden diferente al que se envi. El protocolo de comunicaciones con datagramas es un protocolo sin conexin, es decir, cada vez que se enven datagramas es necesario enviar el descriptor del socket local y la direccin del socket que debe recibir el datagrama. Como se puede ver, hay que enviar datos adicionales cada vez que se realice una comunicacin. Sockets Raw Son sockets que dan acceso directo a la capa de software de red subyacente o a protocolos de ms bajo nivel. Se utilizan sobre todo para la depuracin del cdigo de los protocolos. Diferencias entre Sockets Stream y Datagrama Ahora se nos presenta un problema, qu protocolo, o tipo de sockets, debemos usar - UDP o TCP? La decisin depende de la aplicacin cliente/servidor que estemos escribiendo. Vamos a ver algunas diferencias entre los protocolos para ayudar en la decisin. En UDP, cada vez que se enva un datagrama, hay que enviar tambin el descriptor del socket local y la direccin del socket que va a recibir el datagrama, luego stos son ms grandes que los TCP. Como el protocolo TCP est orientado a conexin, tenemos que establecer esta conexin entre los dos sockets antes de nada, lo que implica un cierto tiempo empleado en el establecimiento de la conexin, que no existe en UDP. En UDP hay un lmite de tamao de los datagramas, establecido en 64 kilobytes, que se pueden enviar a una localizacin determinada, mientras que TCP no tiene lmite; una vez que se ha establecido la conexin, el par de sockets funciona como los streams: todos los datos se leen inmediatamente, en el mismo orden en que se van recibiendo. UDP es un protocolo desordenado, no garantiza que los datagramas que se hayan enviado sean recibidos en el mismo orden por el socket de recepcin. Al contrario, TCP es un protocolo ordenado, garantiza que todos los paquetes que se enven sern recibidos en el socket destino en el mismo orden en que se han enviado. Los datagramas son bloques de informacin del tipo lanzar y olvidar. Para la mayora de los programas que utilicen la red, el usar un flujo TCP en vez de un datagrama UDP es ms sencillo y hay menos posibilidades de tener problemas. Sin embargo, cuando se requiere un rendimiento ptimo, y est justificado el tiempo adicional que supone realizar la verificacin de los datos, los datagramas son un mecanismo realmente til. En resumen, TCP parece ms indicado para la implementacin de servicios de red como un control remoto (rlogin, telnet) y transmisin de ficheros (ftp); que necesitan transmitir datos de longitud indefinida. UDP es menos complejo y tiene una menor sobrecarga sobre la conexin; esto hace que sea el indicado en la implementacin de aplicaciones cliente/servidor en sistemas distribuidos montados sobre redes de rea local. USO DE SOCKETS Podemos pensar que un Servidor Internet es un conjunto de sockets que proporciona capacidades adicionales del sistema, los llamados servicios. Puertos y Servicios

Cada servicio est asociado a un puerto. Un puerto es una direccin numrica a travs de la cual se procesa el servicio. Sobre un sistema Unix, los servicios que proporciona ese sistema se indican en el fichero /etc/services, y algunos ejemplos son: daytime 13/udp ftp 21/tcp telnet 23/tcp telnet smtp 25/tcp mail http 80/tcp La primera columna indica el nombre del servicio. La segunda columna indica el puerto y el protocolo que est asociado al servicio. La tercera columna es un alias del servicio; por ejemplo, el servicio smtp, tambin conocido como mail, es la implementacin del servicio de correo electrnico. Las comunicaciones de informacin relacionada con Web tienen lugar a travs del puerto 80 mediante protocolo TCP. Para emular esto en Java, usaremos la clase Socket. La fecha (daytime). Sin embargo, el servicio que coge la fecha y la hora del sistema, est ligado al puerto 13 utilizando el protocolo UDP. Un servidor que lo emule en Java usara un objeto DatagramSocket. LA CLASE URL La clase URL contiene contructores y mtodos para la manipulacin de URL (Universal Resource Locator): un objeto o servicio en Internet. El protocolo TCP necesita dos tipos de informacin: la direccin IP y el nmero de puerto. Vamos a ver como podemos recibir pues la pgina Web principal de nuestro buscador favorito al teclear: http://www.yahoo.com En primer lugar, Yahoo tiene registrado su nombre, permitiendo que se use yahoo.com como su direccin IP, o lo que es lo mismo, cuando indicamos yahoo.com es como si hubiesemos indicado 205.216.146.71, su direccin IP real. La verdad es que la cosa es un poco ms complicada que eso. Hay un servicio, el DNS (Domain Name Service), que traslada www.yahoo.com a 205.216.146.71, lo que nos permite teclear www.yahoo.com, en lugar de tener que recordar su direccin IP. Si queremos obtener la direccin IP real de la red en que estamos corriendo, podemos realizar llamadas a los mtodos getLocalHost() y getAddress(). Primero, getLocalHost() nos devuelve un objeto iNetAddress, que si usamos con getAddress() generar un array con los cuatro bytes de la direccin IP, por ejemplo: InetAddress direccion = InetAddress.getLocalHost(); byte direccionIp[] = direccion.getAddress(); Si la direccin de la mquina en que estamos corriendo es 150.150.112.145, entonces: direccionIp[0] = 150 direccionIp[1] = 150 direccionIp[2] = 112 direccionIp[3] = 145 Una cosa interesante en este punto es que una red puede mapear muchas direcciones IP. Esto puede ser necesario para un Servidor Web, como Yahoo, que tiene que soportar grandes cantidades de trfico y necesita ms de una direccin IP para poder atender a todo ese trfico. El nombre interno para la direccin 205.216.146.71, por ejemplo, es www7.yahoo.com. El DNS puede trasladar una lista de direcciones IP asignadas a Yahoo en www.yahoo.com. Esto es una cualidad til, pero por ahora abre un agujero en cuestin de seguridad. Ya conocemos la direccin IP, nos falta el nmero del puerto. Si no se indica nada, se utilizar el que se haya definido por defecto en el fichero de configuracin de los servicios del sistema. En Unix se indican en el fichero /etc/services, en Windows-NT en el fichero services y en otros sistemas puede ser diferente. El puerto habitual de los servicios Web es el 80, as que si no indicamos nada, entraremos en el servidor de Yahoo por el puerto 80. Si tecleamos la URL siguiente en un navegador: http://www.yahoo.com:80 tambin recibiremos la pgina principal de Yahoo. No hay nada que nos impida cambiar el puerto en el que residir el servidor Web; sin embargo, el uso del puerto 80 es casi estndar, porque elimina pulsaciones en el teclado y, adems, las direcciones URL son lo suficientemente difciles de recordar como para aadirle encima el nmero del puerto. Si necesitamos otro protocolo, como: ftp://ftp.microsoft.com

el puerto se derivar de ese protocolo. As el puerto FTP de Microsoft es el 21, segn su fichero services. La primera parte, antes de los dos puntos, de la URL, indica el protocolo que se quiere utilizar en la conexin con el servidor. El protocolo http (HyperText Transmission Protocol), es el utilizado para manipular documentos Web. Y si no se especifica ningn documento, muchos servidores estn configurados para devolver un documento de nombre index.html. Con todo esto, Java permite los siguientes cuatro constructores para la clase URL: public URL( String spec ) throws MalformedURLException; public URL( String protocol,String host,int port,String file ) throws MalformedURLException; public URL( String protocol,String host,String file ) throws MalformedURLException; public URL( URL context,String spec ) throws MalformedURLException; As que podramos especificar todos los componenetes del URL como en: URL( "http","www.yahoo.com","80","index.html" ); o dejar que los sistemas utilicen todos los valores por defecto que tienen definidos, como en: URL( "http://www.yahoo.com" ); y en los dos casos obtendramos la visualizacin de la pgina principal de Yahoo en nuestro navegador. DOMINIOS DE COMUNICACIONES El mecanismo de sockets est diseado para ser todo lo genrico posible. El socket por s mismo no contiene informacin suficiente para describir la comunicacin entre procesos. Los sockets operan dentro de dominios de comunicacin, entre ellos se define si los dos procesos que se comunican se encuentran en el mismo sistema o en sistemas diferentes y cmo pueden ser direccionados. Dominio Unix Bajo Unix, hay dos dominios, uno para comunicaciones internas al sistema y otro para comunicaciones entre sistemas. Las comunicaciones intrasistema (entre dos procesos en el mismo sistema) ocurren (en una mquina Unix) en el dominio Unix. Se permiten tanto los sockets stream como los datagrama. Los sockets de dominio Unix bajo Solaris 2.x se implementan sobre TLI (Transport Level Interface). En el dominio Unix no se permiten sockets de tipo Raw. Dominio Internet Las comunicaciones intersistemas proporcionan acceso a TCP, ejecutando sobre IP (Internet Protocol). De la misma forma que el dominio Unix, el dominio Internet permite tanto sockets stream como datagrama, pero adems permite sockets de tipo Raw. Los sockets stream permiten a los procesos comunicarse a travs de TCP. Una vez establecidas las conexiones, los datos se pueden leer y escribir a/desde los sockets como un flujo (stream) de bytes. Algunas aplicaciones de servicios TCP son: File Tranfer Protocol, FTP Simple Mail Transfer Protocol, SMTP TELNET, servicio de conexin de terminal remoto Los sockets datagrama permiten a los procesos utilizar el protocolo UDP para comunicarse a y desde esos sockets por medio de bloques. UDP es un protocolo no fiable y la entrega de los paquetes no est garantizada. Servicios UDP son: Simple Network Management Protocol, SNMP Trivial File Transfer Protocol, TFTP (versin de FTP sin conexin) Versatile Message Transaction Protocol, VMTP (servicio fiable de entrega punto a punto de datagramas independiente de TCP) Los sockets raw proporcionan acceso al Internet Control Message Protocol, ICMP, y se utiliza para comunicarse entre varias entidades IP. MODELO DE COMUNICACIONES CON JAVA En Java, crear una conexin socket TCP/IP se realiza directamente con el paquete java.net. A continuacin mostramos un diagrama de lo que ocurre en el lado del cliente y del servidor:

El modelo de sockets ms simple es: El servidor establece un puerto y espera durante un cierto tiempo (timeout segundos), a que el cliente establezca la conexin. Cuando el cliente solicite una conexin, el servidor abrir la conexin socket con el mtodo accept(). El cliente establece una conexin con la mquina host a travs del puerto que se designe en puerto# El cliente y el servidor se comunican con manejadores InputStream y OutputStream Hay una cuestin al respecto de los sockets, que viene impuesta por la implementacin del sistema de seguridad de Java. Actualmente, los applets slo pueden establecer conexiones con el nodo desde el cual se transfiri su cdigo. Esto est implementado en el JDK y en el intrprete de Java de Netscape. Esto reduce en gran manera la flexibilidad de las fuentes de datos disponibles para los applets. El problema si se permite que un applet se conecte a cualquier mquina de la red, es que entonces se podran utilizar los applets para inundar la red desde un ordenador con un cliente Netscape del que no se sospecha y sin ninguna posibilidad de rastreo. APERTURA DE SOCKETS Si estamos programando un cliente, el socket se abre de la forma: Socket miCliente; miCliente = new Socket( "maquina",numeroPuerto ); Donde maquina es el nombre de la mquina en donde estamos intentando abrir la conexin y numeroPuerto es el puerto (un nmero) del servidor que est corriendo sobre el cual nos queremos conectar. Cuando se selecciona un nmero de puerto, se debe tener en cuenta que los puertos en el rango 0-1023 estn reservados para usuarios con muchos privilegios (superusuarios o root). Estos puertos son los que utilizan los servicios estndar del sistema como email, ftp o http. Para las aplicaciones que se desarrollen, asegurarse de seleccionar un puerto por encima del 1023. En el ejemplo anterior no se usan excepciones; sin embargo, es una gran idea la captura de excepciones cuando se est trabajando con sockets. El mismo ejemplo quedara como: Socket miCliente; try { miCliente = new Socket( "maquina",numeroPuerto ); } catch( IOException e ) { System.out.println( e ); } Si estamos programando un servidor, la forma de apertura del socket es la que muestra el siguiente ejemplo: Socket miServicio; try { miServicio = new ServerSocket( numeroPuerto ); } catch( IOException e ) { System.out.println( e ); }

A la hora de la implementacin de un servidor tambin necesitamos crear un objeto socket desde el ServerSocket para que est atento a las conexiones que le puedan realizar clientes potenciales y poder aceptar esas conexiones: Socket socketServicio = null; try { socketServicio = miServicio.accept(); } catch( IOException e ) { System.out.println( e ); } CREACION DE STREAMS Creacin de Streams de Entrada En la parte cliente de la aplicacin, se puede utilizar la clase DataInputStream para crear un stream de entrada que est listo a recibir todas las respuestas que el servidor le enve. DataInputStream entrada; try { entrada = new DataInputStream( miCliente.getInputStream() ); } catch( IOException e ) { System.out.println( e ); } La clase DataInputStream permite la lectura de lneas de texto y tipos de datos primitivos de Java de un modo altamente portable; dispone de mtodos para leer todos esos tipos como: read(), readChar(), readInt(), readDouble() y readLine(). Deberemos utilizar la funcin que creamos necesaria dependiendo del tipo de dato que esperemos recibir del servidor. En el lado del servidor, tambin usaremos DataInputStream, pero en este caso para recibir las entradas que se produzcan de los clientes que se hayan conectado: DataInputStream entrada; try { entrada = new DataInputStream( socketServicio.getInputStream() ); } catch( IOException e ) { System.out.println( e ); } Creacin de Streams de Salida En el lado del cliente, podemos crear un stream de salida para enviar informacin al socket del servidor utilizando las clases PrintStream o DataOutputStream: PrintStream salida; try { salida = new PrintStream( miCliente.getOutputStream() ); } catch( IOException e ) { System.out.println( e ); } La clase PrintStream tiene mtodos para la representacin textual de todos los datos primitivos de Java. Sus mtodos write y println() tienen una especial importancia en este aspecto. No obstante, para el envo de informacin al servidor tambin podemos utilizar DataOutputStream: DataOutputStream salida; try { salida = new DataOutputStream( miCliente.getOutputStream() ); } catch( IOException e ) { System.out.println( e ); } La clase DataOutputStream permite escribir cualquiera de los tipos primitivos de Java, muchos de sus mtodos escriben un tipo de dato primitivo en el stream de salida. De todos esos mtodos, el ms til quizs sea writeBytes(). En el lado del servidor, podemos utilizar la clase PrintStream para enviar informacin al cliente: PrintStream salida; try { salida = new PrintStream( socketServicio.getOutputStream() ); } catch( IOException e ) {

System.out.println( e ); } Pero tambin podemos utilizar la clase DataOutputStream como en el caso de envo de informacin desde el cliente. CIERRE DE SOCKETS Siempre deberemos cerrar los canales de entrada y salida que se hayan abierto durante la ejecucin de la aplicacin. En la parte del cliente: try { salida.close(); entrada.close(); miCliente.close(); } catch( IOException e ) { System.out.println( e ); } Y en la parte del servidor: try { salida.close(); entrada.close(); socketServicio.close(); miServicio.close(); } catch( IOException e ) { System.out.println( e ); } SERVIDOR DE ECO En el siguiente ejemplo, vamos a desarrollar un servidor similar al que se ejecuta sobre el puerto 7 de las mquinas Unix, el servidor echo. Bsicamente, este servidor recibe texto desde un cliente y reenva ese mismo texto al cliente. Desde luego, este es el servidor ms simple de los simples que se pueden escribir. El ejemplo que presentamos, ecoServidor.java, maneja solamente un cliente. Una modificacin interesante sera adecuarlo para que aceptase mltiples clientes simultneos mediante el uso de threads. import java.net.*; import java.io.*; class ecoServidor { public static void main( String args[] ) { ServerSocket s = null; DataInputStream sIn; PrintStream sOut; Socket cliente = null; String texto; // Abrimos una conexin con breogan en el puerto 9999 // No podemos elegir un puerto por debajo del 1023 si no somos // usuarios con los mximos privilegios (root) try { s = new ServerSocket( 9999 ); } catch( IOException e ) { } // Creamos el objeto desde el cual atenderemos y aceptaremos // las conexiones de los clientes y abrimos los canales de // comunicacin de entrada y salida try { cliente = s.accept(); sIn = new DataInputStream( cliente.getInputStream() ); sOut = new PrintStream( cliente.getOutputStream() ); // Cuando recibamos datos, se los devolvemos al cliente

// que los haya enviado while( true ) { texto = sIn.readLine(); sOut.println( texto ); } } catch( IOException e ) { System.out.println( e ); } }

CLIENTE/SERVIDOR TCP/IP Mnimo Servidor TCP/IP Veamos el cdigo que presentamos en el siguiente ejemplo, minimoServidor.java, donde desarrollamos un mnimo servidor TCP/IP, para el cual desarrollaremos despus su contrapartida cliente TCP/IP. La aplicacin servidor TCP/IP depende de una clase de comunicaciones proporcionada por Java: ServerSocket. Esta clase realiza la mayor parte del trabajo de crear un servidor. import java.awt.*; import java.net.*; import java.io.*; class minimoServidor { public static void main( String args[] ) { ServerSocket s = (ServerSocket)null; Socket s1; String cadena = "Tutorial de Java!"; int longCad; OutputStream s1out; // Establece el servidor en el socket 4321 (espera 300 segundos) try { s = new ServerSocket( 4321,300 ); } catch( IOException e ) { System.out.println( e ); } // Ejecuta un bucle infinito de listen/accept while( true ) { try { // Espera para aceptar una conexin s1 = s.accept(); // Obtiene un controlador de fichero de salida // con el socket s1out = s1.getOutputStream(); // Enviamos nuestro texto longCad = sendString.length(); for( int i=0; i < longCad; i++ ) s1out.write( (int)sendString.charAt( i ) ); // Cierra la conexin, pero no el socket del servidor s1.close(); } catch( IOException e ) { System.out.println( e ); } } }

asociado

} Mnimo Cliente TCP/IP El lado cliente de una aplicacin TCP/IP descansa en la clase Socket. De nuevo, mucho del trabajo necesario para establecer la conexin lo ha realizado la clase Socket. Vamos a presentar ahora el cdigo de nuestro cliente ms simple, minimoCliente.java, que encaja con el servidor presentado antes. El trabajo que realiza este cliente es que todo lo que recibe del servidor lo imprime por la salida estndar del sistema. import java.awt.*; import java.net.*; import java.io.*; class minimoCliente { public static void main( String args[] ) throws IOException { int c; Socket s; InputStream sIn; // Abrimos una conexin con breogan en el puerto 4321 try { s = new Socket( "breogan",4321 ); } catch( IOException e ) { System.out.println( e ); } // Obtenemos un controlador de fichero de entrada del socket y // leemos esa entrada sIn = s.getInputStream(); while( ( c = sIn.read() ) != -1 ) System.out.print( (char)c ); // Cuando se alcance el fin de fichero, cerramos la conexin y // abandonamos s.close(); } }

EJECUTAR TCP/IP EN Windows '95 Las indicaciones que se proporcionan a continuacin, van a permitirnos fijar los parmetros de Windows '95 para que se puedan ejecutar programas cliente y servidor, sin necesidad de que el ordenador en el cual se est ejecutando Windows '95 est conectado a una red de rea local. Esto puede resultar til para mucha gente que est probando Java en su casa y no dispone de red, o incluso para aquellos programadores o estudiosos que quieren probar sus nuevos programas distribuidos pero no disponen de red o de Internet. Advertencia: Si los siguientes parmetros se van a fijar en un ordenador porttil que en ocasiones s se conecte a una red, sera conveniente anotar los parmetros actuales de la

configuracin de Windows '95, para que sean fcilmente recuperables cuando este ordenador se vuelva a conectar a la red. Configuracin del TCP/IP de Windows '95 Hay que seguir los pasos que vamos a relatar a continuacin, suponemos que se est ejecutando la versin espaola de Windows '95, en otras versiones puede que las opciones tengan nombre diferente: En el Panel de Control, seleccionar Red Picar Agregar, luego Protocolo y luego Agregar Seleccionar Microsoft y luego TCP/IP y picar en Aceptar En este momento probablemente se solicite la introduccin de los discos de Windows '95, o del CD-ROM Seleccionar la pestaa Configuracin de la ventana Red Seleccionar TCP/IP en la lista que aparece y picar Propiedades Seleccionar la pestaa Direccin IP Crearse una direccin IP, como por ejemplo: 102.102.102.102 Crearse una Mscara de subred, como: 255.255.255.0 Seleccionar la pestaa Configuracin DNS y desactivar DNS Los valores correspondientes a las otras cuatro pestaas pueden dejarse los que hay por defecto Picar Aceptar (Opcional) Seleccionar la pestaa Identificacin de la ventana Red (Opcional) Introducir un nombre para el ordenador, como por ejemplo: breogan (Opcional) Picar Aceptar Crear una entrada en la "red" Editar el fichero hosts.sam que est en el directorio de Windows Al final del fichero incorporar la direccin IP y el nombre del ordenador que se han introducido antes, en nuestro caso: 102.102.102.102 breogan Asegurarse de que la direccin IP y el nombre coinciden con la direccin IP que se ha fijado en el paso 7a de antes y que el nombre es el mismo que el indicado en el paso 12 anterior Salvar el fichero con el nombre "hosts" y reiniciar Windows '95 Comprobacin de la red Abrir una sesin MS-DOS Teclear "ping breogan" Debera aparecer: Pinging breogan [102.102.102.102] with 32 bytes of data: Reply from 102.102.102.102: bytes=32 time=1ms TTL=32 Reply from 102.102.102.102: bytes=32 time<10ms TTL=32 Reply from 102.102.102.102: bytes=32 time<10ms TTL=32 Reply from 102.102.102.102: bytes=32 time<10ms TTL=32 Teclear "tracert 102.102.102.102" Debera aparecer: Tracing route to 102.102.102.102 over a maximum of 30 hops 1 <10 ms 1 ms <10 ms 102.102.102.102 Trace complete. En este instante, si todo ha ido bien, el ordenador est listo para funcionar como si estuviera en red. Dos o ms programas que se comuniquen en red a travs de sockets debera poder ejecutarse ahora dentro de los dominios del ordenador que acabamos de configurar Problemas ms frecuentes Los tres problemas que pueden presentarse cuando intentemos comprobar el funcionamiento correcto de la red interna que acabamos de montar son: Cuando hacemos "ping" obtenemos "Bad IP address breogan" Intentar teclear "ping 102.102.102.102". Si ahora s se obtiene rplica, la causa del problema es que el los pasos 12 de la Configuracin y 3 de la Creacin de la entrada en la tabla de hosts, no se ha introducido correctamente el nombre de la mquina. Comprobar esos pasos y que todo coincide. El programa cliente o el servidor fallan al intentar el "connect" La causa podra estar en que se produzca un fallo por fichero no encontrado en el directorio Windows/System de las libreras WINSOCK.DLL o WSOCK32.DLL. Muchos programas que se utilizan en Internet reemplazan estos ficheros cuando se instalan. Asegurarse de que estn estos ficheros y que son los originales que vienen con la distribucin de Windows '95.

El programa servidor dice que no puede "bind" a un socket Esto sucede porque tiene el DNS activado y no puede encontrar ese DNS o servidor de direcciones, porque estamos solos en la red. Asegurarse de que en el paso 8 de la Configuracin la opcin de DNS est deshabilitada.

También podría gustarte