Tutorial Java A.A.

18
Introducción a Java Encapsulamiento en Java Método main Flujos de Control en Java Declaración de una clase en Java Control de Acceso a Miembros de Clase This, en Clases de Java Clases en Java de Utilidad Métodos de clase Origen de los Patrones de Diseño Ventajas de utilizar Patrones de diseño El Patrón Proxy El Patrón Bridge (Puente) El Patrón Iterador (Iterator) Conceptos de programación Palabras Reservadas Java

description

Tutorial Java Alfredo A.

Transcript of Tutorial Java A.A.

Introducción a Java Encapsulamiento en Java Método main Flujos de Control en Java Declaración de una clase en Java Control de Acceso a Miembros de Clase This, en Clases de Java Clases en Java de Utilidad Métodos de clase Origen de los Patrones de Diseño Ventajas de utilizar Patrones de diseño El Patrón Proxy El Patrón Bridge (Puente) El Patrón Iterador (Iterator) Conceptos de programación Palabras Reservadas Java

Introducción a Java

Aunque los inicios de Java se remontan a 1991, fecha en la que los ingenieros de Sun Microsystems trataban

de diseñar un lenguaje de programación para electrodomésticos, Java se introduce como lenguaje de

programación a finales de 1995.

Java, según lo describe Sun, es un lenguaje simple, orientado a objetos, distribuido, interpretado, robusto,

seguro, de arquitectura neutra, portable, de altas prestaciones, multitarea y dinámica. Muchos de estos conceptos se irán explicando en sucesivos capítulos. La verdad es que java es un lenguaje muy completo y en

el que casi todo depende de todo. Es por eso por lo que su aprendizaje se orienta de forma iterativa: a partir

de una visión muy general se va refinando en sucesivas iteraciones.

Existen distintos programas comerciales que permiten desarrollar código en Java. Nosotros prestaremos atención a Sun Microsystems que distribuye gratuitamente dos productos:

Java(tm) Development Kit (JDK): conjunto de programas y librerías que permiten compilar y ejecutar

programas escritos en Java. Incorpora además un depurador (Debugger) para ejecutar

parcialmente un programa, revisar los valores de variables, etc. con el objetivo de corregir errores de codificación.

Java Runtime Environment (JRE): se trata de una versión reducida del JDKdestinada únicamente a la

ejecución de código Java.

Los programas en Java se construyen con clases. Instanciando estas clases se podrán crear cualquier

cantidad de objetos. Se puede pensar en una clase como en una plantilla para construir objetos. Las clases estarán compuestas por dos tipos demiembros: los campos, o datos de la clase, y los métodos, o acciones

que se pueden realizar sobre los datos.

Ahora podemos comenzar a sumergirnos en Java. Veamos para ello un programa muy sencillo, el clásico

ejemplo del programa que imprime "Hola Mundo": HolaMundo.java

Holamundo.java declara una clase llamada HolaMundo . Los miembros de la clase aparecen entre llaves. Esta clase tendrá un miembro, el método denominando main . Este método se ejecuta cuando ejecutamos la clase

como aplicación.

El único parámetro del método main es un vector de objetos String que son los argumentos con los que se

invocará al programa desde la línea de órdenes. voidindica que el método main no devuelve ningún valor. La única sentencia que contiene el método main invoca al método println en el objetoout de la clase System.

Esta sentencia imprime una cadena con terminación de salto de línea en el flujo de salida estándar.

Encapsulamiento en Java

Imaginemos que se crea una clase, una docena de programadores tienen acceso a dicha clase y la utilizan a

discreción, posteriormente dicha clase comienza a comportarse de una manera inesperada debido a que los valores que algunas variables han tomado no fueron anticipados y todo comienza a desmoronarse. Para

corregir el problema se crea una versión más nueva de dicha clase y listo.

Bueno, a esto le llamamos flexibilidad y capacidad de mantenimiento, ambas son características y beneficios de la programación Orientada a Objetos (OO) pero para que una clase pueda cumplir dichas funciones los

programadores debemos de hacer algo. Imaginemos que creamos una clase con variables de instancia

públicas a las cuales podemos acceder sin problemas desde fuera de la misma clase...

Analizando el código anterior podemos darnos cuenta de que las variables enteras tipo y clase son públicas y pueden ser accedidas directamente a través de una instancia de la clase MiClase, esto compila sin ningún

problema, digamos que es 'legal', sin embargo, ¿qué pasa si ingresamos un valor que no se supone debe de

tener una variable (en este caso el -5 que le asignamos a tipo)?, simplemente no hay nada que nos detenga

para hacerlo. La única manera de proteger el código es escribiendo un método que nos permita regular los valores que cada variable puede tener y escondiendo las variables para que no se pueda acceder a ellas de

manera directa, esto es el principio básico de encapsulamiento.

Si se desea flexibilidad, buen mantenimiento y extensibilidad, nuestro diseño en el código debe de incluir encapsulamiento, para ello debemos de hacer lo siguiente:

1. Mantener las variables de instancia protegidas (puede ser con un modificador de acceso, p.ej.,

private).

2. Hacer métodos de acceso públicos para forzar al acceso a las variables por medio de dichos métodos en lugar de acceder directamente.

3. Utilizar las convenciones de código para los nombres de los métodos, p. ej., set y get.

El ejemplo anterior modificado para un buen encapsulamiento quedaría así:

Si nos fijamos un poquito, en el método setTipo() no existen validaciones para prevenir que un valor no válido sea asignado a la variable, sin embargo, el proveer de un método de este tipo desde el diseño inicial de la

aplicación nos permite posteriormente modificar el comportamiento de la misma sin afectar los métodos

utilizados, tal vez en un futuro se desee que dicha variable solamente pueda tener uno entre un rango de

valores y se podrán aplicar posteriormente los cambios sin que haya repercusiones negativas.

Método main en Java

El método main proporciona el mecanismo para controlar la aplicación. Cuando se ejecuta una clase Java el

sistema localiza y ejecuta el método main de esa clase. Veamos un ejemplo

Los argumentos del array de cadenas son los "argumentos de la clase". El programa imprimiría por pantalla

estos argumentos. Así para realizar una posible ejecución de la aplicación escribiríamos en la línea de

comandos: java imprime hola que tal estas

Obteniéndose como resultado:

hola que tal estas

El método main debe ser public, static y void(no devuelve nada)

Flujos de Control en Java

Un programa java está compuesto por una serie de sentencias. Las dos sentencias básicas en el lenguaje Java se reflejan en la siguiente tabla:

sentencias de declaración que son las que hemos estudiado para declarar variables y constantes.

sentencias de expresión

Expresión de asignación, a = b+c;

Formas prefijas o posfijas de ++ y --, contador++;

Llamadas a métodos, Objeto1.mimetodo();

Expresiones de creación de objetos Sentencias de control

Estas últimas son las que controlan el flujo de ejecución del programa. Normalmente el orden de ejecución de

sentencias es el mismo en el que están escritas. Sin embargo, las sentencias de control de flujo introducen bifurcaciones en la ejecución del programa. A continuación estudiaremos en detalle cada uno de los tipos de

sentencias.

if-else

La sentencia if-else nos permite elegir entre dos alternativas de flujo diferentes. La ejecución del programa dependerá del resultado de evaluar la expresión booleana,

si el valor de expresion_booleana es true se ejecutará el bloque_de_sentencias1, en caso contrario, si hay

parte else, se ejecuta el bloque_de_sentencias2. La cláusulaelse es opcional.

Si queremos que un programa compruebe la edad de una determinada persona para saber si es menor de edad o no, bastaría con preguntar en una sentencia if-else si la variable edad, que es donde tenemos

almacenada la edad de la persona, es menor que dieciocho. En caso afirmativo, aplicaremos un descuento del

5% y en caso contrario del 15%.

Supongamos que además de saber si alguien es mayor o menor de edad queremos aplicar un nuevo descuento para jubilados. Podemos cambiar el problema y anidar sentencias if-else.

switch La sentencia switch selecciona entre un grupo de sentencias en función de la evaluación de una expresión. Su

formato sería:

si se encuentra una etiqueta case cuyo valor_integral coincida con el de la expresiónselector se trasfiere el

control a su correspondiente bloque_de_sentencias. En caso de que ningún valor coincida se ejecuta el bloque_de_sentencias correspondiente a la etiqueta default.

En la sentencia switch no es necesario escribir break al final de cada case. Si falta la sentencia break el

código de la siguiente sentencia case se ejecutará hasta que se encuentre un break. Tal es el caso del

siguiente ejemplo, donde se traduce una nota numérica a su correspondiente nota verbal.

Vemos como cuando la nota es un 7 al no tener un break continúa la ejecución hasta el siguiente case, el 8,

imprimiendo NOTABLE. Lo mismo sucede con el SOBRESALIENTE.

Todas las etiquetas case deben ser expresiones constantes, es decir, literales o identificadores declarados

como static final e inicializados con un valor constante. for

Esta sentencia se usa para realizar un bucle a lo largo de un rango de valores desde el principio hasta el final,

Lo habitual es usar for cuando queremos recorrer todo un rango de valores de una variable. De esta

forma, expresion_inicial indica el punto de partida para hacer iteraciones, expresion_incremento cómo se va a

ir incrementando la variable yexpresion_booleana expresa que condición debe cumplirse para que el bucle for acabe.

Al principio el contador i lo inicializamos a 1 pues el uno es un divisor para cualquier número. Iremos

incrementando i de uno en uno y calculando el módulo de la división del numero entre i. La condición de salida

del bucle es cuando el contador sea menor o igual que la mitad del número, pues no habrá divisores con un valor mayor.

El bucle for sólo acaba cuando se cumple la condición de salida o cuando en elbloque_de_sentencias se

encuentra una sentencia break. Sin embargo, debido a que se utiliza para iterar a lo largo de un rango de

valores, romper el bucle es de mal estilo. while y do-while

Con la sentencia while se repite el bloque_de_sentencias hasta que la expresión booleana sea falsa. Un

bucle while sería:

El bucle while puede no ejecutarse nunca pues la expresion_booleana puede ser falsa la primera vez que se evalúa. Como hay veces que se desea que el bucle se ejecute al menos una vez, en Java tenemos también la

instrucción do-while:

aquí la expresión booleana se evalúa al final por lo que bloque_de_sentencias se ejecuta al menos una vez.

break y continue

Las sentencias break y continue se utilizan dentro de los bucles y modifican el flujo natural de los mismos. La sentencia break provoca la salida inmediata del bucle que estemos ejecutando, sin realizar la ejecución del

resto de las sentencias. La sentencia break se puede usar tanto en bucles como en bifurcaciones. El siguiente

uso de break en el bucle while nos garantiza que j no será nunca negativo, pues en ese caso romperá el bucle

y continuará con la ejecución normal:

La sentencia continue finaliza la iteración que en ese momento se está ejecutando, salta al final del cuerpo

del mismo y evalúa la expresión booleana que controla dicho bucle. Se suele usar un continue para saltarse

un elemento del rango de valores que recorre el bucle. El uso de continue en el siguiente código evita que se

produzca una división por cero al calcular el valor de aux.

return

La sentencia return termina la ejecución de un método y devuelve al invocador el control de flujo del

programa. En el caso de que la función devuelva alguna variable, este valor se deberá poner a continuación

del return, return <valor>. El siguiente ejemplo nos enseña un uso de la sentencia return para determinar si un número es positivo:

EsPositivo.java

Declaración de una Clase en Java

Vimos como los elementos principales de una clase son sus atributos (datos) y sus métodos (código para

manipular los datos). Veamos una clase simple, Publicacion que podríamos utilizar para almacenar los datos

sobre nuestra colección bibliográfica:

El nombre de la clase, Publicacion debe ser un identificador válido en Java y por convención, empieza por letra

mayúscula. Una declaración de clase crea un nombre de tipo en Java. De esta forma las referencias a objetos Publicacion se pueden declarar con un simple:

Las variables de una clase se llaman campos. La clase Publicacion tiene tres campos, idPublicacion que

identifica de forma unívoca cada publicación, titulo que es el título de la publicación y autor que ha firmado la publicación.

Podríamos definir un campo propietario. Con este campo indicaríamos el propietario del libro. Sería útil, si sólo

vamos a almacenar nuestras publicaciones, que el valor de este campo lo compartan todas los objetos que

podamos definir a partir de esta clase. Calificaríamos la declaración de este campo con la palabra reservada

static:

Control de Acceso a Miembros de una Clase en Java

Cuando se definió la clase Publicacion, el campo idPublicacion se pensó para que se generase de forma

automática y de forma coherente. Por tanto cualquier modificación externa sobre este campo podría dejar al objeto en un estado inconsistente, y podríamos tener dos objetos con el mismo identificador. Queremos por

tanto que este campo sólo se pueda leer y no pueda ser modificado por ningún otro objeto. Para ello se

"oculta" este campo y se proporciona un método público para poder acceder a su valor:

¿Qué hemos conseguido? Ahora para acceder al valor del campo idPublicacion será necesario utilizar el método id. Y la única forma de modificar este campo será por medio de métodos internos a la

clase Publicacion .

Estos mecanismos que regulan el acceso se denominan métodos de acceso y se resumen en la siguiente tabla:

Método Descripción

private Un miembro privado es accesible sólo para la clase en la que está definido.

protected La propia clase, las subclases y todas las clases dentro del mismo paquete tienen acceso a los miembros calificados

con este método de acceso.

public Todas las clases tienen acceso a los miembros públicos de la clase.

package Sólo las clases del mismo paquete que la clase tienen acceso a los miembros

En los constructores de las clases, se pueden utilizar especificadores de acceso para indicar que objetos pueden crear ejemplares de su clase: private si ninguna clase puede crear un objeto de su clase, sólo se

podrá crear por medio de métodos públicos de la clase, protected cuando sólo las subclases pueden crear

objetos, public si cualquiera puede crear objetos de esta clase y package-access cuando sólo desde los

objetos pertenecientes al mismo paquete se pueden crear objetos de esa clase.

This, Clases Java

Hay ocasiones en las que resulta útil referirse al objeto desde el que se está ejecutando un método. En esas

ocasiones se puede usar la referencia especial de objeto this, pero cuidado, siempre dentro de un método no

estático.

Esta referencia se suele usar para pasar una referencia al objeto actual como un parámetro para otros métodos. La siguiente llamada añadiría el objeto a una relación de publicaciones prestadas:

Se usa this cuando un atributo está oculto por una declaración de variable o parámetro. Por ejemplo:

En el segundo constructor titulo y autor están ocultos por los parámetros con el mismo nombre. Para garantizar que accedemos al campo adecuado en lugar de al parámetro del método, le colocamos el

prefijo this

Clases en Java de Utilidad

Las clases de utilidad son estructuras de datos, es decir, estructuras que nos sirven para la organización de

los datos. En este apartado veremos las más comunes que nos servirán, en las siguientes lecciones, para

poder crear estructuras más complejas.

Array

Un vector (array) es una manera de agrupar un conjunto de valores bajo un mismo nombre. La manera de acceder a aquellos es mediante un número denominadoíndices. Todos los valores pertenecientes a un vector

tendrán el mismo tipo.

La declaración de un tipo vector en Java puede hacerse de dos maneras:

int vector[];

int[] vector;

En ambos casos obtendríamos un vector de enteros. Aunque ambas formas son correctas, utilizaremos la

segunda manera, que separa la declaración de tipo del nombre de la variable.

Los vectores en Java se tratan como objetos de una clase predefinida. Los arrays pueden asignarse a objetos

de la clase Object y los métodos de Object pueden utilizarse con vectores. Por tanto deben crearse llamando

a un constructor con new, aunque el constructor tenga una sintaxis totalmente distinta a la estudiada hasta

ahora:

int vector[] = new int[30];

También se pueden inicializar con valores entre llaves separados por comas:

Esta declaración es lo mismo que crear el vector por medio de un constructor e ir asignándole los valores uno a uno:

Como puede observar, se accede a los elementos de un vector con los corchetes y uníndice que varía de 0 a

la longitud del vector menos uno. Esto también es válido cuando queremos consultar los valores del vector:

Vectores.java

Se puede acceder al número de elementos de un vector con la variable miembro implícita length. Rescribiendo el programa anterior:

Conviene recordar que los vectores son objetos porque, a la hora de pasar argumentos a una función, se

pasarán por referencia.

Un detalle importante es el valor con el que se inicializan lo elementos del vector. Cuando se crea el vector los

elementos se inicializan con el valor por defecto del tipo correspondiente (cero para valores numéricos,

carácter nulo para char, false paraboolean, null para String y referencias).

Los argumentos del array de cadenas son los "argumentos de la clase". El programa imprimiría por pantalla

estos argumentos. Así para realizar una posible ejecución de la aplicación escribiríamos en la línea de

comandos:

java imprime hola que tal estas

Obteniéndose como resultado:

hola que tal estas

El método main debe ser public, static y void(no devuelve nada)

Métodos de Clase

Los métodos de una clase constituyen la lógica de la clase, es decir, contienen el código que manipula el

estado del objeto. Además constituyen el mecanismo utilizado para implementar los mensajes entre objetos. Quiere decir, cuando un objeto se comunica con otro por un mensaje lo hace por medio de la invocación al

método correspondiente del objeto. Y el mecanismo para invocar un método en java es por medio de las

referencias usando el operador de la siguiente forma:

referencia.metodo (parametros);

Declaración de los Métodos

Veamos la forma de declarar un método. La estructura general de una declaración tiene dos partes, la

declaración y el cuerpo del método.

La Declaracion_del_metodo proporciona información sobre su nombre, la accesibilidad del método, el número de parámetros que recibe, etc. El Cuerpo_del_metodo contiene el conjunto de sentencias que manipula los

datos de cada objeto.

Sobrecarga de métodos

Cada método tiene una "firma" por así decirlo, que son su nombre, el tipo y número de sus parámetros. Existe

una característica para tener dos métodos (ó constructores) con el mismo nombre. Esta característica se denominasobrecarga de métodos.

Hemos estudiado la construcción de distintos constructores para una clase y hemos puesto como ejemplo el

caso de una clase Publicacion. Veamos lo implementado hasta el momento y cómo los constructores nos dan

un ejemplo de sobrecarga de métodos:

El compilador resolverá que constructor debe ejecutar en cada momento en función del número de

parámetros y su tipo. Si se llama al constructor sin parámetros se ejecutará el primer constructor y en caso de hacerlo con dos parámetrosString se ejecutará el segundo.

Nota: El concepto de sobrecarga de métodos se puede aplicar siempre que los parámetros sean diferentes, bien por su

tipo, bien por que el número de parámetros de un método o otro es diferente. Hay que tener cuidado con los tipos: int,

byte y short ya que aunque son tipos diferentes, si hacemos la llamada aún método con un número entero no sabría a cual

de los métodos llamar, ya que un entero puede ser considerado de las tres formas. Con double y float no pasa, porque

acordaros que hemos de forzar a que Java entienda un decimal como float, sino lo entiende como double.

Origen de los Patrones de Diseño

Los patrones surgen al realizar un esfuerzo mental para generalizar la solución a problemas diversos y

aparentemente independientes. Por tanto, cualquiera puede encontrar y utilizar sus propios patrones de diseño a través de la experiencia. Además, los patrones son un buen vehículo para transmitir dicha

experiencia a otras personas.Veamos un ejemplo:

Supongamos que hemos terminado una aplicación de generación de facturas. Una parte de nuestro diseño

contiene el siguiente diagrama de clases:

En otra ocasión diseñamos una aplicación de gestión de un almacén de repuestos, donde nos encontramos con este diagrama de clases en una parte del diseño:

Se trata de dos estructuras muy similares, pero no es esto lo que nos sugiere la existencia de un patrón. Sino

el papel que juegan estas estructuras en el diseño. Y, en efecto, dicho papel se repite en ambos casos:

Factura es algo que se compone de varias Líneas de factura, y además, las líneas de factura no tienen sentido sin la existencia de la Factura.

Almacén es algo que se compone de Repuestos, y además, los repuestos requieren la existencia de un

Almacén.

Hemos dado con un patrón de diseño, se trata de una idea: un objeto que almacena otros objetos, y éstos últimos no tienen sentido sin su "almacén". Se trata del patrón "Continente-Contenido":

Pero no es el único patrón que podemos encontrar:

Línea de Factura es un objeto que se compone necesariamente de Concepto, Cantidad y Precio..

Repuesto es un objeto que se compone necesariamente de Pieza, Garantía y Precio.

Aquí hay otra idea que se puede generalizar: un objeto que se desglosa en otros objetos. Podríamos llamarlo

el patrón "Objeto-componente":

Cuando nos enfrentamos a un nuevo problema intentaremos aplicar los patrones que conozcamos, y esto no

es una sugerencia, sino el comportamiento natural de todo ser humano. Por otra parte, es muy importante

tener en cuenta que los patrones no sólo surgen y se aplican a diseños diferentes. Un mismo patrón puede aplicarse varias veces en un mismo diseño.

Ventajas de utilizar Patrones de diseño

Como hemos dicho, los patrones son meras ideas que no están exentas de sus ventajas e inconvenientes. El

uso continuado de estas ideas pone de manifiesto, de manera natural, dichas ventajas e inconvenientes, de

manera que se conocen a priori. Por tanto, es posible elegir el patrón mas adecuado a nuestras necesidades, pero no eludir sus inconvenientes. Esto es algo a sopesar en cada caso, no obstante, el criterio para decidir la

bondad de un patrón con respecto a un problema es bien conocido. Estos son los aspectos de un patrón que

se deben evaluar:

Resistencia al cambio: se debe elegir el patrón que facilite lo más posibles futuros cambios. Los cambios en un diseño no son probables, son seguros, se producen con toda seguridad. A la hora de

diseñar una solución a un problema es conveniente abstraer el problema concreto a otro más

genérico y resolver este último. Los patrones consiguen precisamente esto.

Reutilización: este aspecto requiere una aclaración importante. La reutilización de código resulta prácticamente imposible. En cambio, los diseños son mucho más reutilizables, pero ni siquiera tanto

como las propias ideas. Se debe tender a reutilizar las ideas. Por eso, cuando hacemos un diseño

debemos pensar en que nos debe ser útil para futuros proyectos, en su esencia o filosofía, no en su

estructura o implementación. Así, lo conveniente es buscar patrones nuevos en diseños nuevos,

documentarlos y almacenarlos como una parte importante de nuestra experiencia. Son como una "álbum de fotos" de nuestros viajes.

En general, la gran ventaja del uso de patrones es que minimizan el riesgo de generar un mal diseño y

permiten comunicar experiencias entre diseñadores.

El Patrón Proxy

Este patrón consiste en interponer un intermediario (Proxy) entre un objeto y los demás que lo utilizan. Se diferencia del patrón Adaptador en que el objeto "adaptado" solamente puede ser manipulado a través del

objeto Proxy.

Se suele utilizar para implementar comportamientos "vagos" (lazy). Por ejemplo, si tenemos muchos objetos

imagen en un documento, se tardaría mucho tiempo en abrir el documento al cargar las imágenes de disco. Para evitarlo podemos sustituir los objetos imagen por objetos proxyImagen, con el mismo interfaz, pero que

solamente cargan la imagen cuando se va a visualizar.

Debemos insistir en dos aspectos que caracterizan el patrón Proxy:

El objeto Apoderado tiene el mismo interfaz que el objeto "Protegido". Para facilitar esto se puede

derivar el objeto Apoderado de la misma clase padre que el objeto "Protegido", pero no es

absolutamente necesario.

El objeto "Protegido" solamente puede ser manipulado por su correspondiente Apoderado.

Un ejemplo típico de aplicación del patrón proxy es el de un editor de documentos. El editor podrá incluir

imágenes y dibujos complejos, y se plantea el problema de recuperar todos estos costosos objetos cada vez

que se abre el documento. La aplicación del patrón proxy soluciona el problema definiendo un

"representante", que ocupe su lugar, hasta que sea necesario cargarlos.

El Patrón Bridge (Puente)

Como sabemos, una abstracción puede tener diferentes implementaciones. El mecanismo de herencia permite

que la implementación de una abstracción evolucione sin modificar significativamente el diseño. Esto es cierto

mientras la abstracción en sí misma (básicamente, su interfaz) no evolucione. Es decir, no se puede modificar

independientemente una implementación y la abstracción a la que está ligada. Este patrón consigue que esto sea posible.

La parte importante del esquema son las clases Abstracción yClaseObjetoImplementor. Los descendientes de Abstracción son "evoluciones" de la abstracción que pueden o no mantener la implementación. Al mismo

tiempo, los descendientes de ClaseObjetoImplementador son "evoluciones" de la implementación

independientes de la evolución de Abstracción.

El esquema estático es el siguiente:

El Patrón Iterador (Iterator)

Este patrón se utiliza en relación a objetos que almacenan colecciones de otros objetos, por ejemplo, las

listas. El uso de un objeto Iterador permite recorrer los elementos del agregado independientemente de su organización. Si todos los objetos agregado (listas, árboles, etc) generan un objeto Iterador con el mismo

interfaz resulta muy fácil operar con ellos y se facilitan los cambios de implementación.

El objeto agregado puede crear objetos Iterador para la implementación concreta de dicho agregado.

Diferentes implementaciones, diferentes iteradores. A partir de entonces, un objeto cliente puede manipular el

agregado únicamente a través del iterador. Si cambiamos la implementación del agregado (por ejemplo, la

lista pasa a ser un árbol), el objeto cliente no resulta afectado. Se trata de un patrón muy común y ampliamente utilizado. En el caso de las listas, podríamos recorrerla sin exponer su estructura interna,

permitiendo así diferentes tipos de listas (listas normales, con vectores, etc) y diferentes tipos de iteradores:

Conceptos de Programación

Un proceso es la ejecución de un programa, es decir, los datos e instrucciones están cargados en la memoria

principal, ejecutándose o esperando a hacerlo.

Un proceso no tiene porqué estar siempre en ejecución. Puede pasar por diferentes estados:

Preparado: Un proceso preparado es el que está preparado para ejecutarse. Sólo le "falta" la CPU En Ejecución: Un proceso en ejecución es un proceso que "tiene" CPU, se está ejecutando

Bloqueado: Un proceso bloqueado está esperando que ocurra un suceso antes de poder "usar" la CPU. Dicho suceso suele ser una operación de Entrada / Salida: pulsar una tecla, leer de disco... Pero

también puede ser que esté esperando a que otro proceso haga algo

1. Creación del proceso. Está preparado para ejecutarse

2. El proceso se ejecuta en CPU 3. El proceso espera a que ocurra un suceso y se bloquea

4. Ocurre el suceso por el que esperaba el proceso. Está preparado para ejecutarse

5. El proceso "sale" de la CPU

6. Fin de la ejecución del proceso

No es necesario cumplir todos los pasos, por ejemplo, podría ser que un proceso hiciera los pasos 1-2-6.

Desde el punto de vista del Hardware, dependiendo del número de CPU's, un sistema puede ser:

Sistema Monoprocesador

Sistema Multiprocesador o Sistema fuertemente acoplado

o Sistema débilmente acoplado

Como su nombre indica, un sistema monoprocesador es aquel en el que sólo hay una CPU; y como todos

habréis imaginado, un sistema multiprocesador es el que tiene varias CPU's. Éste último se divide en 2

tipos. Los sistemas fuertemente aclopados, en los que hay memoria común y los débilmente acoplados, en los que no hay memoria común. Un ejemplo de los fuertemente acoplados es un PC con varios

procesadores, y otro de los débilmente acoplados es una red de ordenadores.

Desde el punto de vista del Software, también hay diferentes tipos de sistemas, atendiendo a cómo se

ejecutan los procesos:

Sistema de Multiprogramación

Sistema de Multiprocesamiento

La Multiprogramación consiste en que todos los procesos se ejecuten en la misma CPU. Esto se consigue

mediante la intercalación de la ejecución de los procesos.

En Multiprocesamiento cada proceso se ejecuta en una CPU. En este caso hay paralelismo real en la

ejecución de los procesos.

Además de la programación imperativa o secuencial y la programación concurrente, hay otros

paradigmas o enfoques de la programación.

La programación imperativa se centra en la transformación que hay que realizar para procesar los datos, pasando estos a un segundo plano. En cambio, la programación orientada a objetos gira en torno a un

nuevo concepto: el objeto. Éste comprende tanto procesos como datos. Aunque pueda parecer más

complejo, este tipo de programación se asemeja a la forma que tiene el ser humano de ver el mundo, frente a

la programación imperativa que está orientada a la máquina. Para entenderlo mejor, un objeto es "una cosa con límites definidos", como por ejemplo, una pelota, que tiene características (datos como tamaño o color),

asociadas a unas operaciones (procesos como botar o lanzar) aplicables sobre el objeto. Otras operaciones no

son válidas. No puedes beberte una pelota... aunque el mundo es muy raro y hay de todo. Otra característica

importante de la programación orientada a objetos es la herencia. Este mecanismo se utiliza para estructurar el programa en forma jerárquica.

La programación declarativa es otra visión de la programación, en la que no se describe cómo obtener los

resultados, sino qué es lo que debemos obtener. Se divide en 2 tipos, la programación lógica y

la programación funcional.

Hace unos años, cuando todavía no existían los entornos gráficos, ni el hardware que los soportara, todo se

hacía en un entorno de consola. Al abrir una ventana de msdos en windows, o una consola de comandos en

unix... entran escalofríos sólo de pensar que las cosas eran antes "tan frías". Eso si, no se colgaban de vez en

cuando sin saber porqué. Primero Apple copiando de Xerox, y después Microsoft copiando de Apple, crearon los entornos visuales, con lo que vino la revolución multimedia y se disparó el negocio de la informática.

Dichos entornos visuales constan de una interfaz gráfica "más amigable", además de ofrecernos un amplio

abanico de posibilidades. No hay que creer que los entornos multitarea aparecieron con entornos visuales en

que se puede "tener abiertas muchas ventanitas". UNIX siempre ha sido multitarea, desde el modo consola.

Ahora vamos a hacer un pequeño repaso de las arquitecturas existentes dentro del mundo de la informática. Cuando en los años 60 se empezaron a comercializar los ordenadores, disponibles sólo para empresas debido

a su alto coste, se utilizabansistemas centralizados o mainframes, que tenían diferentes consolas para dar

acceso a múltiples usuarios. Todo el trabajo lo realizaba el mainframe. En los años 80 surgió el PC, con un

precio más asequible. Nacieron los sistemas en red que permiten interconectar ordenadores de diferentes características compartiendo recursos. El siguiente paso fueron los sistemas distribuidos en los que hay

diferentes estaciones interconectadas, aunque el usuario no necesita conocer su ubicación, como sucede en

los sistemas en red. El acceso a los recursos es transparente, es decir, se accede a los recursos como si

fueran locales, aunque no lo sean. También existen sistemas paralelos, que constan de varios procesadores operando conjuntamente.

Una vez aclarados ciertos conceptos, es hora de empezar con el curso de Metodología de la Programación.

Palabras Reservadas en Java

En este capítulo hay un listado de palabras reservadas Java orientado a objetos. Las palabras reservadas son identificadores, pero como su nombre indica, estas palabras están reservadas, y no se pueden usar como identificadores de usuario.

abstract

assert

boolean

break

byte

case

catch

char

class

const

continue

default

do

double

else

enum

extends

final

finally

float

for

goto

if

implements

import

instanceof

int

interface

long

native

new

package

private

protected

public

return

short

static

strictfp

super

switch

synchronized

this

throw

throws

transient

try

void

volatile

while