Вы находитесь на странице: 1из 586

Introduccin a la Informtica

Conceptos bsicos
Informtica
Ordenador
Hardware y software
Codificacin de la informacin
Cdigo binario
Bits y bytes
Estructura funcional de un ordenador: Arquitectura von Neumann
Unidades de entrada y de salida
Memoria (principal y auxiliar)
CPU = ALU + UC
Soporte lgico de los ordenadores
Sistema operativo
Software de aplicacin
Apndices
Historia de la Informtica
Componentes de un PC

Lecturas recomendadas
Alberto Prieto, Antonio Lloris & Juan Carlos Torres:
Introduccin a la Informtica, 3 edicin, captulo 1
McGraw-Hill / Interamericana de Espaa, 2002

Conceptos bsicos
Informtica
del francs
en ingls

informatique (INFORmacin autoMTICA)


Computer Science

Ciencia que estudia el tratamiento de la informacin


por medio de mquinas automticas.
Conjunto de conocimientos cientficos y tcnicas que hacen posible el
tratamiento automtico de la informacin por medio de ordenadores.
Campo de conocimiento que abarca
todos los aspectos de diseo y uso de ordenadores

Ordenador
Mquina capaz de aceptar unos datos de entrada, efectuar con ellos
operaciones lgicas y aritmticas, y proporcionar los datos resultantes a travs de
un medio de salida; todo ello sin la intervencin de un operador humano y bajo
el control de un programa de instrucciones previamente almacenado en el
ordenador.
vs. Calculadora Mquina capaz de efectuar operaciones aritmticas
bajo el control directo del usuario:
- No realiza operaciones de tipo lgico
- No enlaza automticamente las operaciones que realiza
Ejemplos de operaciones aritmticas y lgicas
- Operaciones aritmticas:
sumar, restar, multiplicar, dividir...
- Operaciones lgicas:
comparaciones, operaciones del lgebra de Boole...

Introduccin a la Informtica

-1-

Fernando Berzal

Hardware y software
HARDWARE [Soporte fsico]
La mquina en s; es decir, el conjunto de circuitos electrnicos, cables,
dispositivos electromecnicos y otros elementos fsicos que forman los
ordenadores
SOFTWARE [Soporte lgico]
Conjunto de programas ejecutables por el ordenador.

El trmino hardware no se utiliza nicamente para designar los dispositivos


fsicos del ordenador, sino tambin todo lo relacionado con ellos.
ARQUITECTURA DE COMPUTADORES

Lo mismo puede decirse del software: no trata slo de los programas de


ordenador, sino de todas las materias relacionadas con la construccin y uso de
los programas (organizacin y estructuracin de los datos, anlisis de
aplicaciones, metodologas de diseo, etc.).
INGENIERA DEL SOFTWARE

Un ordenador necesita ambos soportes, tan imprescindible es el hardware


como el software. Aunque son muy distintos y sus disciplinas relacionadas son
diferentes, hardware y software son complementarios ya que el ordenador
necesita de ambos para su funcionamiento.

Introduccin a la Informtica

-2-

Fernando Berzal

El ordenador como sistema


Caja negra cuyas salidas dependen de las entradas

Teniendo en cuenta las instrucciones del programa almacenado en el ordenador:


Datos de salida = f (Datos de entrada, Instrucciones)

Dato
Representacin formal de hechos, conceptos o instrucciones adecuada para su
comunicacin, interpretacin y procesamiento por seres humanos o medios
automticos.
Ejemplos: 25C, 25m, 1234-BCD, 4/10/2004...

En el interior del ordenador, todo se representa con ceros y unos.

Informacin
El significado que un ser humano le asigna a los datos.
Introduccin a la Informtica

-3-

Fernando Berzal

Codificacin de la informacin
Codificar es representar los elementos de un conjunto mediante los de otro, de
forma tal que a cada elemento del primer conjunto le corresponda un elemento
distinto del segundo.

Cdigo binario
En el interior de los ordenadores digitales actuales, la informacin se
almacena y se transfiere de un sitio a otro segn un CDIGO BINARIO.
El cdigo binario utiliza nicamente dos smbolos diferentes: {0, 1}
Cualquier dato que introduzcamos en el ordenador o que sea manipulado
por l se codifica en su interior por una sucesin de ceros y unos (que
fsicamente se representa por corrientes elctricas, campos magnticos,
marcas pticas...)
En la entrada y la salida del ordenador, los cambios de cdigo se realizan
de forma automtica para que no tengamos que introducir ni interpretar la
informacin codificada.

Bits
La unidad ms elemental de informacin en el interior de un ordenador es
un valor binario (0 1). Esta unidad elemental de informacin se denomina BIT
(BInary uniT).
Un bit representa la informacin correspondiente a la ocurrencia de un
suceso de dos posibilidades (opciones) distintas.
Cualquier suceso que tenga ms de dos posibilidades no podr
representarse con un nico bit, ya que faltaran valores para codificar la
informacin. Para que una codificacin sea correcta, a cada elemento de un
conjunto se ha de asignar un elemento distinto del otro conjunto.

Introduccin a la Informtica

-4-

Fernando Berzal

Ejemplo de codificacin

Mensaje
Confirmo asistencia

Cdigo Morse
--
-

---
-
-

-
-- --

-- -

Alfabeto (cdigo) Morse


A

Codificacin binaria (ASCII)


01000011 01001111 01000110 01001001 01010010 01001101 01001111
01000001 01010011 01001001 01010011 ...
Cdigo binario (ASCII)
A

01000001

01001000

10100101

01010101

01000010

01001001

01001111

01010110

01000011

01001010

01010000

01010111

01000100

01001011

01010001

01011000

01000101

01001100

01010010

01011001

01000110

01001101

01010011

01011010

01000111

01001110

01010100

Introduccin a la Informtica

-5-

Fernando Berzal

Bytes
Usualmente, la informacin se representa por medio de caracteres. A cada
carcter le corresponde un cierto nmero de bits. Un BYTE es el nmero de bits
necesario para almacenar un carcter. Este nmero depende del cdigo utilizado
(generalmente, 8).
Para medir la capacidad de almacenamiento del un ordenador se utilizan
mltiplos del byte:

Kilobyte
Megabyte
Gigabyte
Terabyte

1 KB
1 MB
1 GB
1 TB

210 bytes
220 bytes
230 bytes
240 bytes

1 024 bytes
1 048 576 bytes
1 073 741 824 bytes
1 099 511 627 776 bytes

Ejemplos
Datos
Texto

1 novela de 200 pginas, 50 lneas por


pgina y 80 caracteres por lnea

Imagen en
blanco y negro
Imagen
en color
Sonido de
baja calidad
Sonido de
alta calidad
Vdeo
(calidad VHS)
Vdeo
(calidad DVD)

1024x768 pxeles, 1 bpp (bit por pxel)


1024x768 pxeles, 24 bpp (bits por pxel)
3 minutos, 11000 muestras por segundo,
8 bits por muestra
3 minutos, 44100 muestras por segundo,
12 bits por muestra, dos canales (estreo)
90 minutos, 25 fotogramas por segundo,
352x288 pxeles de resolucin, 24 bpp
90 minutos, 25 fotogramas por segundo,
720x576 pxeles de resolucin, 24 bpp

Tamao
800 000 bytes
(unos 780 KB)
98 304 bytes
(menos de 100KB)
2 359 296 bytes
(unos 2300KB)
1 980 000 bytes
(casi 2MB)
23 814 000 bytes
(casi 23MB)
41 057 280 000 bytes
(casi 40GB)
167 961 600 000 bytes
menos de 160GB !!!

NOTA: Existen tcnicas de compresin de datos que permiten


almacenar los datos en menos espacio del mostrado en la tabla.

Introduccin a la Informtica

-6-

Fernando Berzal

Estructura funcional
de un ordenador:
Arquitectura von Neumann

IDEA CLAVE: El programa se almacena en memoria junto con los datos.

Unidades de entrada
Dispositivos por medio de los cuales se introducen datos e instrucciones en el
ordenador.
vg: Teclado, ratn, cmara digital, escner, lector de cdigos de barras...

Unidades de salida
Dispositivos por donde se obtienen los resultados de los programas ejecutados
por el ordenador.
vg: Monitor, impresora, plotter, sintetizador de voz...

Introduccin a la Informtica

-7-

Fernando Berzal

Memoria
Donde se almacenan, por un corto o largo perodo de tiempo, tanto los datos
como las instrucciones.
Memoria principal/central/interna
La que trabaja a mayor velocidad
RAM [Random Access Memory]: De lectura y escritura, suele ser voltil.
ROM [Read Only Memory]: Slo lectura (no se puede modificar), permanente.
:

Para que un programa se ejecute,


debe estar cargado (almacenado) en la memoria principal

Se estructura en posiciones de un determinado nmero de bits (palabras de


memoria) a las que se accede por su direccin.

Memoria auxiliar/secundaria/externa/masiva
Ms lenta, pero de mayor capacidad que la memoria principal
:

Los datos y programas se suelen almacenar en la memoria auxiliar para


que, cuando se ejecute varias veces un programa o se utilicen
repetidamente unos datos, no sea necesario introducirlos de nuevo.

vg:

Dispositivos de almacenamiento
como discos magnticos y pticos, cintas magnticas...

Introduccin a la Informtica

-8-

Fernando Berzal

CPU [Central Processing Unit]


CPU = ALU + UC

Unidad aritmtico-lgica (UAL o ALU)


Unidad encargada de efectuar las operaciones aritmticas y lgicas

Unidad de control (UC)


Detecta seales de estado procedentes de las distintas partes del ordenador y
genera seales de control dirigidas a todas las unidades para controlar el
funcionamiento de la mquina.
:

Capta de la memoria principal las instrucciones del programa que ejecuta


el ordenador, las descodifica y las ejecuta una a una.

Contiene un reloj que sincroniza todas las operaciones elementales


involucradas en la ejecucin de una instruccin.

La frecuencia del reloj (en Megahertzios, MHz, o Gigahertzios, GHz)


determina, en parte, la velocidad de funcionamiento del ordenador.

Microprocesador (P)
CPU contenida en uno
o varios circuitos integrados (chips)

Introduccin a la Informtica

-9-

Fernando Berzal

Ejecucin de un programa
Una vez cargado el programa en memoria, se le cede el control del ordenador:
1. Se lee una instruccin del programa.
2. La unidad de control decodifica la instruccin
3. La unidad de control enva las seales necesarias para ejecutar la instruccin:
a. Se leen los datos de entrada (1 2)
b. Se efecta una operacin con ellos en la ALU (p.ej. suma)
c. Se almacena el resultado
4. Se determina cul debe ser la siguiente instruccin que se debe ejecutar.
5. Se vuelve al paso 1.

Tipos de instrucciones
Instrucciones de transferencia de datos
Mover datos de un sitio a otro
Instrucciones de tratamiento
Realizacin de operaciones aritmticas y lgicas
Instrucciones de bifurcacin y saltos
Alteracin del orden secuencial de ejecucin de las instrucciones
p.ej.: Llamadas/retornos de subrutinas

Otras
p.ej.: Peticin de interrupciones, detencin de la CPU...

Introduccin a la Informtica

- 10 -

Fernando Berzal

Clasificacin de los ordenadores


Segn el uso que se les da:
Ordenador de propsito general: Admiten distintos tipos de
aplicaciones que slo dependen del programa que se ejecuta.
Ordenador de propsito especfico: Slo admite una aplicacin
concreta, utiliza muy pocos programas y las unidades de E/S suelen estar
adaptadas para la aplicacin en que se emplea.
vg:

electrodomsticos (lavadoras, microondas...)


electrnica de consumo (TVs, vdeos, cmaras...)
perifricos (impresoras, escneres...)
sistemas de comunicaciones (telfonos, mdems...)
vehculos (encendido, transmisin, ABS, airbag...)
sistemas de control industrial y robots
sistemas militares (misiles...)

Clasificacin de los ordenadores de propsito general


Prieto, Lloris & Torres: Introduccin a la Informtica
(en funcin de su capacidad, de mayor a menor)

Introduccin a la Informtica

- 11 -

Fernando Berzal

Soporte lgico de los ordenadores


Soporte lgico = Software = Programas
Programas de Aplicacin
Sistema Operativo

Clasificacin
Software de sistema
Sistema operativo (SO)
Herramientas / utilidades (complementos del SO)
Optimizacin de recursos (p.ej. desfragmentador de disco)
Diagnstico del sistema
Herramientas de administracin
Backup (p.ej. compresin de archivos)
Antivirus (McAffee, Norton, Panda...)

Software de aplicacin
Programacin
Traductores (compiladores/intrpretes)
Depuradores
Editores de texto
Entornos integrados de desarrollo (IDEs)

Herramientas ofimticas (p.ej. suites = paquetes integrados)


Procesamiento de textos (MS Word, Lotus WordPro, WordPerfect)
Bases de datos (MS Access, Lotus Approach)
Hojas de clculo (MS Excel, Lotus 1-2-3)
Grficos raster/matriciales/retoque fotogrfico (Adobe Photoshop, Paint Shop Pro)
Grficos vectoriales (Corel Draw, MS Visio)
Autoedicin (MS Publisher, Adobe Illustrator, QuarkXpress)
Colaboracin / groupware (Lotus Notes)

Ciencia/Ingeniera
CAD/CAM (AutoCAD, Cadence)
Clculo matemtico (Mathematica, Matlab, SPSS)
Sistemas gestores de bases de datos (Oracle, IBM DB2, Interbase...)

Comunicacin (p.ej. Internet)


Multimedia (imagen & sonido)
Juegos...
Introduccin a la Informtica

- 12 -

Fernando Berzal

Sistemas operativos
Sistema operativo
Conjunto de programas encargado de controlar los recursos del ordenador

Funciones
Evitar que el usuario/aplicacin tenga que conocer con demasiados
detalles el hardware (esto es, servir de puente entre el hardware y los
programas de aplicacin)
Ofrecer una interfaz de usuario que permita ejecutar aplicaciones (p.ej.
interfaz grfica de usuario tipo WIMP)
Mdulos
KERNEL (ncleo del sistema operativo)
- Cargador inicial (arranque del ordenador)
- Administrador de CPU (dispatcher/planificador)
- Administrador de memoria (memoria virtual, swapping)
- Gestor de archivos (FAT, NTFS...)
- Comunicacin entre procesos
- Proteccin de datos y control de acceso
Controladores de dispositivos (drivers)
Herramientas de administracin
Interfaz de usuario (GUI)
Clasificacin
Monousuario
Monotarea

vs.
vs.

Multiusuario
Multitarea

Ejemplos de sistemas operativos


Monotarea
MS-DOS
CP/M

Introduccin a la Informtica

Multitarea
OS/2 (IBM)
MacOS (Apple)
Windows 95/98/Me (uso domstico)
Windows NT/2000 (uso profesional)
Windows XP
UNIX (IRIX, Solaris/SunOS, Linux...)
- 13 -

Fernando Berzal

Sistema operativo monotarea

Sistemas operativos multitarea

Introduccin a la Informtica

- 14 -

Fernando Berzal

La familia de sistemas operativos UNIX (una pequea parte de ella):

La familia de sistemas operativos Windows

Introduccin a la Informtica

- 15 -

Fernando Berzal

Software peligroso
Virus
Pequeo programa diseado para instalarse y ejecutarse en un ordenador
sin permiso del usuario y, habitualmente, con mala intencin
- Funciones: propagarse, defenderse & realizar alguna accin (inocua/daina).
- Suelen permanecer inactivos algn tiempo para propagarse sin ser detectados.
Tipos
- Virus clsicos: Infectan ficheros ejecutables (.exe, .com...)
- Virus de macros: Macros dentro de documentos (Word, Excel...)
- Virus MBR [Master Boot Record]: Infectan el sector de arranque del
disco y permanecen incluso cuando formateamos el disco.

Troyanos
Programas que hacen algo de cara al usuario
y, adems, realizan otras tareas "ocultas".
Bombas lgicas
Software, incluido por los que desarrollaron la aplicacin,
que se activa cuando se dan ciertas condiciones (p.ej. fecha).

Introduccin a la Informtica

- 16 -

Fernando Berzal

Historia de la Informtica
Dispositivos mecnicos
Dispositivos electromecnicos
Primera generacin (1946-1957): Vlvulas de vaco
Segunda generacin (1958-1964): Transistores
Tercera generacin (1965-1970): Circuitos integrados
Cuarta generacin (1971-...): Microprocesadores

As esperaban en 1954 que fuesen los ordenadores personales en 2004...

http://www.snopes.com/inboxer/hoaxes/computer.asp

Dispositivos mecnicos
Fecha
3000 a.C.

Invencin
baco

1612-1614

Varillas de John Napier para calcular

1622

Reglas de clculo (William Oughtred)


Clculo de logaritmos

1642

Mquina de Pascal: Pascalina


Primera mquina capaz de sumar y restar

1674

Mquina de Leibnitz
Sumas, restas, multiplicaciones y divisiones

1801

Telares Jacquard
Tarjetas perforadas controlan el telar

1820

Arithmometer
Primera calculadora producida en masa

1822

Mquina diferencial de Charles Babbage

1834

Mquina analtica de Charles Babbage


Componentes bsicos del ordenador:
Memoria, unidad de clculo y unidad de control de operaciones

baco

Historia de la Informtica

-1-

Fernando Berzal

Regla de clculo

Mquina de Pascal

Historia de la Informtica

-2-

Fernando Berzal

Telares Jacquard

Historia de la Informtica

-3-

Fernando Berzal

Mquina diferencial de Charles Babbage

Charles Babbage
Historia de la Informtica

Ada Augusta Byron


-4-

Fernando Berzal

Dispositivos electromecnicos

Rel
Fecha
1889

Invencin
Mquina tabuladota de Hollerith para el Censo de EE.UU

1914

Ajedrez automtico de Leonardo Torres Quevedo

1938

Z1, de Conrad Zuse (Alemania)

1944

Harvard Mark I, de Howard Aiken (EE.UU)


= IBM Automatic Sequence Control Calculator [ASCC]

Historia de la Informtica

-5-

Fernando Berzal

Primera generacin
Vlvulas de vaco
Fecha
1946

Ordenador
ENIAC (Electronic Numerical Integrator And Computer)

1948

Manchester Mark I
Primer ordenador digital con programa almacenado
Whirlwind (Jay Forrester, MIT)
Primer ordenador de tiempo real
EDSAC (Electronic Delay Storage Automatic Computer)
Maurice Wilkes, Universidad de Cambridge, Inglaterra
ILLIAC I (Universidad de Illinois en Urbana-Champaign)

1949
1949
1952

Primera calculadora electrnica


ABC [Atanasoff-Berry Computer]
Iowa State University, 1939

Historia de la Informtica

-6-

Fernando Berzal

ENIAC (Electronic Numerical Integrator And Computer)


Universidad de Pennsylvania, Philadelphia
John Presper Eckert & John Mauchly
Se inici en 1943 y se termin en 1946, se us hasta 1955
Caractersticas
Codificacin decimal (no binaria)
20 acumuladores de 10 dgitos
Programada manualmente
18,000 vlvulas de vaco
30 toneladas
15,000 pies cuadrados
140kW de consumo de potemcia
5,000 sumas por segundo

EDVAC (Electronic Discrete Variable Automatic Computer) & IAS


IAS (Institute for Advanced Studies), Universidad de Princeton
John von Neumann
1942-1952
Caractersticas
1000 palabras de 40 bits
2 instrucciones de 20 bits
Conjunto de registros en la CPU
- Registro de almacenamiento de memoria (MBR)
- Registro de direccionamiento de memoria (MAR)
- Registro de instruccin
- Registro de buffer de instruccin
- Contador de programa
- Acumulador
- Multiplicador cociente

Arquitectura von Neumann


(concepto de programa almacenado)
La memoria principal almacena programas y datos
La ALU opera con datos binarios
La unidad de control interpreta instrucciones de la memoria

Historia de la Informtica

-7-

Fernando Berzal

Primeras empresas de Informtica


Fecha
1896

Empresa
Tabulating Machines Co. (Herman Hollerith)

1911

CTR: Calculating, Tabulating, and Recording Co.


Fusin de Tabulating Machines con otras dos empresas

1924

IBM: International Business Machines


Cambio de nombre de CTR (Thomas J. Watson)

1938

HP: Hewlett-Packard
Desde un garage de Palo Alto (William Hewlett & David Packard)

1958

DEC: Digital Equipment Corporation

Remington-Rand Corporation:
UNIVAC Division (Universal Automatic Computer)
UNIVAC I (1951)
Primer ordenador comercial, empleado para el censo de EEUU en 1951
UNIVAC 1103A (1953)
Primera mquina comercial con memoria de ncleos de ferrita

IBM (Internacional Business Machines)


IBM 701 (1952), Defense Calculador
Primer ordenador de programa almacenado de IBM
IBM 650 (1953), Magnetic Drum Calculador
Primer ordenador electrnico producido en masa
IBM 702 (1955)
701 para aplicaciones de negocios
IBM 704 (1955): STRETCH
Supercomputador: 100x 5 kFLOPS!!!
Historia de la Informtica

-8-

Fernando Berzal

Segunda generacin
Transistores
1958-1964

Inventados en los laboratorios Bell en 1947


por John Bardeen, Walter Brattain y William Shockley,
reemplazaron a las vlvulas de vaco:
Menor tamao
Menor coste de fabricacin
Menor disipacin de calor
Menor consumo elctrico
Mayor fiabilidad

Fecha
1957
1960
1961
1964
1965

Ordenador
Atlas Guidance Computer (Burroughs)
Control del lanzamiento del misil Atlas
DEC PDP-1 (Digital Equipment Corporation)
Primer ordenador comercial con monitor y teclado
IBM 7030, Stretch
30x ms rpido que el IBM 704
CDC 6600 (Control Data Corporation)
Primer supercomputador comercial
DEC PDP-8 (Digital Equipment Corporation)
Primera minicomputadora

DEC PDP-8
Historia de la Informtica

-9-

Fernando Berzal

Tercera generacin
Circuitos integrados

Inventados en 1958:
Jack Kilby en Texas Instruments
Robert Noyce en Fairchild Semiconductor
Fecha
1965
1964

Ordenador
Burroughs B2500 y B3500
Primeros ordenadores con circuitos integrados
IBM anuncia su lnea de ordenadores System/360

1972

DEC PDP-11/45

1976

Cray-1
Primer supercomputador vectorial
DEC VAX-11/780

1978

IBM 360
Ley de Moore (Gordon Moore, ejecutivo de Intel):
El nmero de transistores en un chip se duplica cada 18 meses
Menor tamao = Menor consumo = Mejor rendimiento
Historia de la Informtica

- 10 -

Fernando Berzal

Cuarta generacin
Microprocesadores
Primer microprocesador (de 4 bits)
Intel 4004 (1971), 108kHz, unos 4004 transistores
Microprocesadores de 8 bits
Intel 8008 (1972), Intel 8080 (1974) e Intel 8085 (1976)
Microprocesadores de 16 bits
Intel 8086 (1978), 4.77 MHz
Microprocesadores de 32 bits
Intel 80386 (1985)
Microprocesadores de 64 bits
DEC Alpha (1992)
Intel Itanium, IA-64
Microprocesadores utilizados en PCs
CPUs

Ao(s) Transistores

8086 & 8088


80286
80386DX & 80386SX
80486 (SX, DX, DX2 & DX4)
Pentium
Cyrix 6X86
AMD K5
IDT WinChip C6
Pentium MMX
IBM/Cyrix 6x86MX
IDT WinChip2 3D
Pentium Pro
AMD K6
Pentium II
AMD K6-2
Mobile Pentium II
Mobile Celeron
Pentium III
AMD K6-3
Pentium III CuMine
AMD Athlon original
AMD Athlon Thunderbird
Pentium 4

1978-81
1984
1987-88
1990-92
1993-95
1996
1996
1997
1997
1997
1998
1995
1997
1997
1998
1999

Historia de la Informtica

1999
2000
2001

- 11 -

29,000
134,000
275,000
1,200,000
3,100,000
--3,500,000
4,500,000
6,000,000
6,000,000
5,500,000
8,800,000
7,500,000
9,300,000
27,400,000
18,900,000
9,300,000
?
28,000,000
22,000,000
37,000,000
42,000,000

Fernando Berzal

Intel 4004

Intel Pentium 4

Historia de la Informtica

- 12 -

Fernando Berzal

Algunos ordenadores populares...


Fecha
1973
1975
1976
1977
1980
1981
1981
1983
1983
1984
1984
1988
1993

Ordenador
Alto (Xerox PARC: PC experimental con ratn, Ethernet y GUI)
MITS Altair 8800 (primer ordenador personal comercial)
Apple I (Steve Jobs & Steve Wozniak)
Apple II
Osborne 1 (primer ordenador porttil)
Xerox Star (versin comercial del Alto)
IBM PC (arquitectura abierta)
IBM PC-XT
Apple Lisa
IBM PC-AT (80286)
Apple Macintosh
Apple Next
Apple Newton (primer PDA)

Altair

Alto

Apple I

Osborne 1

Macintosh

IBM PC-XT

Newton
http://oldcomputers.net/
http://www.theoldcomputer.com/
http://www.old-computers.com/
http://www.computer.org/history/

Historia de la Informtica

- 13 -

Fernando Berzal

Arquitectura von Neumann

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

-1-

Componentes de un PC

Aspecto exterior de un PC de sobremesa (sin perifricos):

Componentes fsicos bsicos:


1 Fuente de alimentacin
1 Placa base (buses y puertos)
1 Microprocesador (CPU)
1 Memoria RAM
1 Dispositivos de almacenamiento
(disquetera, disco duro)
Fernando Berzal & Nicols Marn
Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

-2-

Microprocesador

Fabricante
vg: Intel, AMD
Generacin (modelo del microprocesador)
vg: Intel Pentium 4, AMD Athlon
La frecuencia interna del reloj (Hz)
vg: > 2 GHz
Slo la parte interna del microprocesador funciona a esa frecuencia.
Tamao de palabra (bits)
vg: 32 bits
Memoria cach interna
vg: 512KB

CPU

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

-3-

Evolucin histrica de las CPUs


Primer microprocesador: Intel 4004 (1971)

CPUs
8086 and 8088
80286
80386DX and 80386SX
80486SX, 80486DX,
80486DX2 and 80486DX4
Pentium
Cyrix 6X86
AMD K5
IDT WinChip C6
Pentium MMX
IBM/Cyrix 6x86MX
IDT WinChip2 3D
Pentium Pro
AMD K6
Pentium II
AMD K6-2
Mobile Pentium II
Mobile Celeron
Pentium III
AMD K6-3
Pentium III CuMine
AMD original Athlon
AMD Athlon Thunderbird
Pentium 4

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

Ao(s)
1978-81
1984
1987-88
1990-92

Transistores
29,000
134,000
275,000
1,200,000

1993-95
1996
1996
1997
1997
1997
1998
1995
1997
1997
1998
1999

3,100,000
--3,500,000
4,500,000
6,000,000
6,000,000
5,500,000
8,800,000
7,500,000
9,300,000
27,400,000
18,900,000
9,300,000
?
28,000,000
22,000,000
37,000,000
42,000,000

1999
2000
2001

-4-

Memoria RAM

Tamao (bits)

vg: 256 MB

Velocidad
Fecuencia del reloj (MHz)
Tiempo de refresco (ns)

vg: PC-100
10 ns

Deteccin y correccin de errores. vg: Bits de paridad, ECC


Conexin directamente sobre la placa base
n Mdulo SIMM (30 o 72 contactos).
n Mdulo DIMM (168 contactos).
Tipos de memoria RAM (Random Access Memory)
n DRAM (Dynamic RAM): 70-80 ns.
n FPM (Fast Page Mode): 60-70 ns.
n EDO (Extended Data Output-RAM): 50-70ns,
Permite acceder a ella mientras an no se ha terminado el ciclo anterior.

n SDRAM (Synchronous DRAM): 10-25ns.


Funciona de forma sincronizada con la placa base.

n PC100 o SDRAM de 100 MHz.


n PC133: o SDRAM de 133 MHz.
n BEDO (Burst-EDO)
Evolucin de la memoria EDO que compite en prestaciones con la SDRAM.

n RDRAM (Rambus DRAM).


n DDR (Double Data Rate).
RDRAM y DDR pueden transmitir datos al doble de la frecuencia de reloj.
Fernando Berzal & Nicols Marn
Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

-5-

Placa base

Placa ATX
Mejor distribucin de los componentes y circulacin de aire:
CPU colocada junto a la fuente de alimentacin para recibir el
aire del ventilador.
Conectores para teclado y ratn de tipo PS/2.

Baby AT
Basado en el modelo original del IBM PC-AT, fsicamente
compatible con ste pero de dimensiones ms reducidas.
Conector para teclado DIN de 5 pins.

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

-6-

Placa para biprocesador

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

-7-

Placa base: Chipset

Familia de circuitos integrados que sirven para


conectar los distintos componentes de la placa base.

Chipset de Intel

POST
[Power On Self Test]

BIOS
[Basic Input Output System]

Placa base: Memoria cach


Memoria muy rpida
estratgicamente situada entre el procesador y la memoria RAM
Fernando Berzal & Nicols Marn
Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

-8-

Placa base: Zcalo del microprocesador

PGA

Pin Grid Array

ZIF

Zero Insertion Force [socket]


Zcalo ZIF

Slot 1

Ranura de conexin (Intel)

Slot A

Ranura de conexin (AMD)

Slot 1

Placa base: Ranuras de memoria

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

-9-

Placa base: Ranuras de expansin

Buses
1 ISA
1 VLB
1 PCI
Puertos
1 AGP

Placa base: Conectores

Buses
1
1
1
1
1

IDE
EIDE (Enhanced IDE)
SCSI
USB
Firewire (IEEE 1384)

Puertos
1

Puerto serie (RS-232)


1 Puerto paralelo

vg: Modem
vg: Impresora

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 10 -

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 11 -

Puertos PS/2 para ratn y teclado:

Puertos serie

Puerto paralelo

Salida para el monitor

Salidas USB y conexin RJ45 (red)

Puerto multimedia

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 12 -

Dispositivos de almacenamiento

Parmetros
Capacidad (MB, GB, TB)
Velocidad
o Velocidad de transferencia (MB/s)
o Tiempo medio de acceso (ms)

vg: 10MB/s
vg: 14ms (HD)
150ms (CD)

Almacenamiento de informacin
o Dispositivos magnticos: disco 3, disco duro
o Dispositivos pticos: CD-ROM, DVD
Modo de acceso
o Directo (discos)
o Secuencial (cintas)

Conexin va IDE/EIDE, SCSI, USB

Dispositivos de almacenamiento

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 13 -

Disquetes
Tamao

Modelo

Capacidad

Descripcin

5,25"

SS/DD

180 Kb

Una cara, doble densidad.

5,25"

DS/DD

360 Kb

Dos caras, doble densidad.

5,25"

DS/HD

1,2 MB

Dos caras, alta densidad.

3,5 "

DS/DD

720 Kb

Dos caras, doble densidad.

3,5"

DS/HD

1,44 MB

Dos caras, alta densidad (estndar actual)

Disco antiguo de 5

Disco de 3

Discos duros
Velocidad de rotacin en revoluciones por minuto (rpm)
Memoria cach

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 14 -

Discos pticos
CD-ROM
CD-R
CD-RW
DVD

Compact-Disc Read-Only-Memory
Compact-Disc Recordable
Compact-Disc ReWritable
Digital Versatile Disc

Lector de CD

650 MB

4.7 GB

CD-ROMs

Velocidad de los lectores de CD-ROM


1x = 300 KB/s
Tasa de transferencia mxima
Velocidad de la unidad de CD-ROM

2,400 KB/s

3,600

4,800

6,000

7,200

9,000

(16x)

(24x)

(32x)

(40x)

(48x)

(60x)

Velocidad de las grabadoras de CDs

Velocidad de lectura Velocidad de grabacin Velocidad de regrabacin

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 15 -

Cintas magnticas
vg: QIC (120MB), Travan (800MB-4GB), DAT (2GB-4GB)

Unidad de cinta

Cinta magntica

Otros dispositivos de almacenamiento


Jaz

Discos de 1GB y 2GB

Zip

Discos de 100MB, 250MB y 750MB

LS-120

Discos de 120 MB

Memorias flash

Zip

Jaz

LS-120

Memoria flash USB

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 16 -

Perifricos de E/S

Dispositivos a travs de los cuales


el ordenador se comunica con el exterior

Dispositivos de entrada
1 Ratn
1 Teclado

Dispositivos de entrada

1 Escner
1 Cmara
1 Micrfono (tarjeta de sonido)

Dispositivos de salida
1 Impresora
1 Monitor (tarjeta grfica)
1 Altavoces (tarjeta de sonido)

Dispositivos de salida

Dispositivos de entrada/salida
1 Modem
1 Tarjeta de red
Fernando Berzal & Nicols Marn
Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 17 -

Ratn

Tipos de ratones
Mecnicos (bola) u pticos (LEDs)
Conexin va puerto serie (RS-232), PS2 o USB
Normales o inalmbricos (conexin por infrarrojos)

Dispositivos similares
Joystick
Trackball
Touchpad

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 18 -

Teclado

Estndar:

Teclado QWERTY

Conexin:

Puerto para teclado DIN-5 o PS/2

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 19 -

Impresora

Parmetros
Resolucin
Puntos por pulgada (dpi)
vg: 600x300 (600 dpi horizontal x 300 dpi vertical)
Velocidad de impresin
Pginas por minuto (ppm) o caracteres por segundo (cps)
NOTA: Vara en funcin de la resolucin

Conexin: Puerto paralelo o USB

buffer

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 20 -

Tipos de impresoras
1 Impresoras de impacto: margarita, agujas (9, 12, 24)

1 Impresoras de inyeccin de tinta

1 Impresoras lser

Otros dispositivos de impresin

Plotters
Impresoras fotogrficas
Impresoras de gran formato
Impresoras multifuncin

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 21 -

Monitor

Conexin
A travs de la tarjeta grfica.
Parmetros
Tamao
Pulgadas (diagonal)
vg: 15, 17
Resolucin
Pxeles (picture elements)
vg: 1024x768
Distancia entre puntos (dot pitch)
Definicin de las imgenes
vg: 0.28 mm
Frecuencia de refresco (Hz)
vg: > 72Hz
Tipos de monitores
Tubos CRT

Pantallas TFT

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 22 -

Tarjeta grfica

Alternativas
Tarjeta de expansin independiente o integrada en la placa base
Caractersticas
Resolucin mxima (pxeles)
vg: 1024x768
Profundidad de color (bits por pxel o nmero de colores)
vg: 24
Memoria (MB)
vg: 16MB
Modos grficos (configuraciones posibles)
vg: SVGA (800x600, 256 colores)

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 23 -

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 24 -

Modem [MOdulador-DEModulador]

Modem interno

Modem externo

Norma

Explicacin

V.22bis
V.32

Velocidad mxima (bps)


2.400

Comunicaciones mdem-mdem

9.600

V.32bis

14.400

V.34

28.800

V.34+

33.600

V.90

55.600

V.29

Comunicaciones mdem-fax

14.400

V.42 y MNP2-4

Control de errores

No aplicable

V.42bis y MNP5-10

Compresin de datos

No aplicable

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 25 -

Tarjeta de sonido

Caractersticas
Precisin de los conversores A/D y D/A (nmero de bits)
Frecuencia de muestreo
Ejemplo: CD
16 bits, 44100Hz, estreo

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 26 -

Escner

Escner de sobremesa

Escner de mano

Caractersticas
Resolucin (puntos por pulgada, ppp)
Profundidad de color (bits)
Calidad del CCD [Charge-Coupled Device]

Tamao de una imagen


Tamao imagen = L x A x RH x RV x B
L
A
RH
RV
B

Longitud
Anchura
Resolucin horizontal
Resolucin vertical
Bits de color (bits por pxel)

Perifricos relacionados
Lectores de cdigos de barras
Cmaras fotogrficas digitales
Webcams
Fernando Berzal & Nicols Marn
Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 27 -

Otros perifricos y accesorios

UPS [Uninterruptible Power Supply]

UPS

Tarjeta de televisin

Tarjeta TV

Reproductor MP3

Reproductor mp3

Fernando Berzal & Nicols Marn


Departamento de Ciencias de la Computacin e Inteligencia Artificial
Universidad de Granada

- 28 -

Algoritmos y programas
Algoritmo
Secuencia ordenada de pasos que resuelve un problema concreto.
Caractersticas
- Correccin
(sin errores).
- Precisin
(ausencia de ambigedades).
- Repetitividad
(solucin genrica de un problema dado).
- Finitud
(nmero finito de rdenes no implica finitud).
- Eficiencia
(temporal [tiempo necesario] y espacial [memoria utilizada])

Programa
Implementacin de un algoritmo en un lenguaje de programacin
Datos de
entrada

Programa
Instrucciones

Datos de
salida

Conjunto ordenado de instrucciones que se dan al ordenador


indicndole las operaciones o tareas que ha de realizar para resolver un
problema.

Introduccin a la Programacin

-1-

Fernando Berzal

Lenguajes de programacin
Una instruccin es un conjunto de smbolos que representa una orden
para el ordenador: la ejecucin de una operacin con datos.
Las instrucciones se escriben en un lenguaje de programacin:
- Se forman con smbolos tomados de un determinado repertorio
(componentes lxicos)
- Se construyen siguiendo unas reglas precisas (sintaxis)
Lenguaje mquina
El nico que entiende directamente la CPU del ordenador
Depende del modelo de ordenador
Repertorio de instrucciones reducido (operaciones muy elementales)
Muy difcil programar en l (en binario, con cadenas de ceros y unos)
Lenguaje ensamblador
Equivalente al lenguaje mquina, cada lnea de cdigo se traduce en
una instruccin para la mquina.
Le asocia mnemnicos a las operaciones que entiende la CPU
Repertorio de instrucciones reducido (operaciones muy elementales)
Programas difciles de entender
Lenguajes de alto nivel
Permiten que el programador exprese el procesamiento de datos de
forma simblica, sin tener en cuenta los detalles especficos de la
mquina.
Independientes del modelo de ordenador
Proporcionan un mayor nivel de abstraccin
Introduccin a la Programacin

-2-

Fernando Berzal

Ejemplos de lenguajes de programacin de alto nivel


FORTRAN (FORmula TRANslation)
1957, IBM (John Backus)
Orientado a la resolucin de problemas cientficos y tcnicos
COBOL (COmmon Business Oriented Language)
1959, Codasyl (Committee on Data System Languages)
Aplicaciones comerciales de gestin
LISP (LISt Processing)
1959, John McCarthy (MIT)
Procesamiento de datos no numricos (usado en IA)
BASIC (Beginners All-purpose Symbolic Instruction Code)
1964, John Kemeny & Thomas Kurtz (Darmouth College)
Lenguaje interactivo para principiantes
Simula
1967, Ole-Johan Dahl & Krysten Nygaard (Noruega)
Primer lenguaje de programacin orientada a objetos
Pascal
1971, Niklaus Wirth
Lenguaje estructurado diseado para aprender a programar
C
1972, Denis Ritchie (Bell Labs)
Lenguaje pequeo, flexible y eficiente
Smalltalk
1972, Alan Kay (Xerox PARC)
Origen de los interfaces WIMP (Windows, Icons, Mouse & Pull-down menus)
PROLOG (PROgramming in Logic)
1972, Alain Colmerauer (Universidad de Marsella)
Basado en Lgica (usado en IA)
Ada
1980, US Department of Defense
Basado en Pascal, muy usado en aplicaciones militares
Introduccin a la Programacin

-3-

Fernando Berzal

C++
1983, Bjarne Stroustroup (AT&T Bell Labs)
Extensin de C que permite la programacin orientada a objetos
Java
1995, Sun Microsystems
Similar a C++, aunque ms sencillo de aprender y usar.
C#
2000, Microsoft Corporation
Alternativa de Microsoft a Java, muy similar a ste

Clasificacin de los lenguajes de programacin de alto nivel


Lenguajes imperativos:
Los programas indican al ordenador de forma inequvoca los
pasos a seguir para la resolucin de un problema.
o Programacin estructurada:
La estructura del texto del programa debe auxiliarnos para
entender la funcin que realiza: estrategia divide y
vencers (la resolucin de un problema se divide en tareas
y, stas, en subtareas).
Ejemplos: C, Pascal, Fortran...
o Programacin orientada a objetos:
Estilo de programacin que basa la estructura de un
programa en mdulos deducidos de los tipos de objetos que
manipula (en lugar de basarse en las tareas que el sistema
debe realizar).
Ejemplos: Smalltalk, C++, Java, C#...
Lenguajes declarativos (funcionales y lgicos):
Los programas se implementan como conjuntos de funciones (o
reglas lgicas) cuya evaluacin nos dar el resultado deseado.
Ejemplos: LISP, PROLOG...
Introduccin a la Programacin

-4-

Fernando Berzal

Evolucin de los lenguajes de programacin:


Lenguajes imperativos

Introduccin a la Programacin

-5-

Fernando Berzal

Evolucin de los lenguajes de programacin:


Lenguajes declarativos

Introduccin a la Programacin

-6-

Fernando Berzal

Traductores
Los traductores transforman programas escritos en un lenguaje de alto
nivel en programas escritos en cdigo mquina:

Tipos de traductores
Compiladores
Generan un programa ejecutable a partir del cdigo fuente

Intrpretes
Van analizando, traduciendo y ejecutando las instrucciones del
programa una a una. No se traduce una instruccin hasta que la
ejecucin de la anterior haya finalizado.

Herramientas de programacin
Editores, depuradores, profilers...
IDEs (entornos integrados de desarrollo)
Ejemplos Microsoft Visual Studio .NET
Borland C++Builder/Delphi
Eclipse

Introduccin a la Programacin

-7-

Fernando Berzal

Eclipse, un IDE para Java (http://www.eclipse.org)

Microsoft Visual Studio .NET, un IDE para la plataforma .NET


Introduccin a la Programacin

-8-

Fernando Berzal

Desarrollo de aplicaciones informticas:


Ciclo de vida del software
El ciclo de vida de una aplicacin comprende las siguientes etapas:

Planificacin
Delimitacin del mbito del proyecto, estudio de viabilidad, anlisis de riesgos,
estimacin de costos, planificacin temporal y asignacin de recursos.

Anlisis (qu?): Elicitacin de requisitos.


Descripcin clara y completa de qu es lo que se pretende,
incluyendo la presentacin de los resultados que se desean obtener
(formato de las salidas) y la forma en que se va a utilizar la
aplicacin (interfaz de usuario)

Diseo (cmo?): Estudio de alternativas


Diseo arquitectnico: Organizacin de los distintos mdulos
que compondrn la aplicacin (diseo arquitectnico).
Diseo detallado: Definicin de los algoritmos necesarios para
implementar la aplicacin en lenguaje natural, mediante
diagramas de flujo o en pseudocdigo [lenguaje algortmico].

Implementacin:
Adquisicin de componentes, creacin de los mdulos de la
aplicacin en un lenguaje de programacin e integracin de los
recursos necesarios para que el sistema funcione.

Depuracin y pruebas:
Comprobacin del funcionamiento de la aplicacin
Pruebas de unidad y de integracin, pruebas alfa, pruebas beta, test de aceptacin.

Verificacin (si se est realizando lo que se pretenda)


Validacin (si se realiza lo correcto).

Explotacin: Uso y mantenimiento


Mantenimiento correctivo: Correccin de defectos o errores.
Mantenimiento adaptativo: Adaptacin de la aplicacin a nuevas
circunstancias e inclusin de nuevas prestaciones.
Introduccin a la Programacin

-9-

Fernando Berzal

Introduccin a la programacin

Java
La plataforma de programacin Java
Historia
La mquina virtual Java
Herramientas de programacin en Java
Aplicaciones y applets
Aplicacin de ejemplo
Applet de ejemplo
Fases en la creacin y ejecucin de programas en Java
Caractersticas clave de Java
Mitos y realidades

La plataforma Java

La mquina virtual Java


(JVM: Java Virtual Machine)
Imprescindible para poder ejecutar aplicaciones Java.
Las bibliotecas estndar de Java
(Java Application Programming Interface = Java API)
Amplia coleccin de componentes.
El lenguaje de programacin Java
Para escribir aplicaciones.
Introduccin a la Programacin: Java

- 11 -

Fernando Berzal

Historia de Java
Hay versiones distintas sobre el origen, concepcin y
desarrollo de Java, desde la que dice que ste fue un proyecto que
estuvo durante mucho tiempo por distintos departamentos de Sun
sin que nadie le prestara atencin hasta la ms difundida, que
presenta a Java como un lenguaje pensado para pequeos
electrodomsticos:
Hace algunos aos, Sun Microsystems decidi intentar introducirse en el
mercado de la electrnica de consumo y desarrollar programas para pequeos
dispositivos electrnicos. Sun decidi crear una filial, denominada FirstPerson Inc..
El mercado inicialmente previsto para los programas de FirstPerson eran los
equipos domsticos: microondas, tostadoras y, fundamentalmente, televisores
interactivos. En este mercado, dada la falta de pericia de los usuarios, se requeran unos
interfaces mucho ms cmodos e intuitivos que los sistemas de ventanas del momento.
James Gosling decidi que las ventajas aportadas por la eficiencia de C++ no
compensaban el gran coste de la prueba y depuracin de aplicaciones C++. Gosling
haba estado trabajando en un lenguaje de programacin que l haba llamado Oak, el
cual, an partiendo de la sintaxis de C++, intentaba remediar las deficiencias que iba
observando.
El primer proyecto en que se aplic este lenguaje recibi el nombre de proyecto
Green y consista en un sistema de control completo de los aparatos electrnicos y el
entorno de un hogar.
Para ello se construy un ordenador experimental denominado *7
(Star Seven). El sistema presentaba una interfaz basada en la
representacin de la casa de forma animada y el control se llevaba a
cabo mediante una pantalla sensible al tacto. En el sistema apareca
Duke, la mascota de Java.
Posteriormente, se aplic a otro proyecto de VoD (Video On Demand) en el que
se empleaba como interfaz para la televisin interactiva. Ninguno de estos proyectos se
convirti nunca en un sistema comercial.
Cuando en Sun se dieron cuenta de que a corto plazo la televisin interactiva no
iba a ser un gran xito, urgieron a FirstPerson a desarrollar con rapidez nuevas
estrategias que produjeran beneficios. No lo consiguieron y FirstPerson cerr en la
primavera de 1994.
A pesar de este fracaso, Bill Joy, cofundador de Sun y uno de los desarrolladores
principales del Unix de Berkeley, juzg que Internet poda llegar a ser el terreno
adecuado para disputar a Microsoft su primaca casi absoluta en el terreno del software
y vio en Oak el instrumento idneo para llevar a cabo estos planes. Tras un cambio de
nombre, al estar Oak ya registrado como marca, el lenguaje Java fue presentado en
sociedad en mayo de 1995 (Sun World95).
http://java.sun.com/features/1998/05/birthday.html

Introduccin a la Programacin: Java

- 12 -

Fernando Berzal

La mquina virtual Java


Java
Source Code

Java Bytecode
Compilador JIT
o intrprete

Compilador

(javac)
Execution

Java Bytecode
Tiempo
de compilacin

Tiempo
de ejecucin

El compilador de Java genera un cdigo intermedio


independiente de la plataforma (bytecodes).
Los bytecodes pueden considerarse como el lenguaje mquina
de una mquina virtual, la Mquina Virtual Java (JVM).
Cuando queremos ejecutar una aplicacin Java, al cargar el
programa en memoria, podemos
a) Interpretar los bytecodes instruccin por instruccin
b) Compilar los bytecodes para obtener el cdigo mquina
necesario para ejecutar la aplicacin en el ordenador
(compilador JIT [Just In Time]).

De esta forma, podemos ejecutar un programa escrito en Java


sobre distintos sistemas operativos (Windows, Solares, Linux...)
sin tener que recompilarlo, como sucedera con programas
escritos en lenguajes como C.
Introduccin a la Programacin: Java

- 13 -

Fernando Berzal

Uso tpico de Java


Distribucin de aplicaciones a travs de Internet
Aplicaciones (programas independientes)
Applets (pequeas aplicaciones)

Applets
Los applets son programas diseados para ejecutarse como
parte de una pgina web.
Java impone restricciones de seguridad para que los applets no
puedan daar el ordenador en que se ejecutan
Ejemplos: Acceder a ficheros locales
Ejecutar otro programa
Conectarse a otro ordenador desde el nuestro.

Si los applets se compilasen directamente al cdigo mquina


de un ordenador concreto, las personas que accediesen a la
pgina web que contiene el applet desde un ordenador de otro
tipo no podran ejecutar el applet.
Introduccin a la Programacin: Java

- 14 -

Fernando Berzal

Herramientas de programacin en Java


Java SDK [Software Development Kit]
http://java.sun.com
Compilacin de aplicaciones Java: javac
Ejecucin de aplicaciones Java: java
Ejecucin de applets: appletviewer
Generacin de documentacin: javadoc
Creacin de archivos de distribucin JAR [Java ARchives]: jar
Depuracin de aplicaciones Java: jdb
Desensamblador para la mquina virtual Java: javap
Generador de stubs en C: javah
...
Versiones
1995 JDK 1.02
1996 JDK 1.1
1998 JDK 1.2 (Java 2 SDK v1.2)
2000 JDK 1.3 (Java 2 SDK v1.3)
2002 JDK 1.4 (Java 2 Platform, Standard Edition v1.4)
2004 JDK 1.5 (Java 2 Platform, Standard Edition 5.0)
Ediciones
J2SE (Standard Edition): Aplicaciones y applets
J2EE (Enterprise Edition): Servidores de aplicaciones
J2ME (Micro Edition): Aplicaciones para dispositivos mviles

Entornos integrados de desarrollo: IDEs


[Integrated Development Environments]
Gratuitos
Eclipse
(http://www.eclipse.org)
NetBeans
(http://java.sun.com)
Introduccin a la Programacin: Java

De pago
Borland JBuilder
IBM Visual Age for Java
Sybase PowerJ
Metrowerks CodeWarrior
- 15 -

Fernando Berzal

Aplicaciones y applets
Creacin y ejecucin de aplicaciones Java
Editor
Cdigo Java:
Prog.java

de texto

javac Prog.java

Bytecode:
Prog.class

java MyProg

Salida

Creacin y ejecucin de applets


Editor
de texto

Cdigo Java:
App.java
javac App.java
Bytecode:
App.class

Editor
de texto

Pgina web:
App.html
appletviewer MyApp.html

Introduccin a la Programacin: Java

- 16 -

Navegador
Web

Ventana

Fernando Berzal

Aplicacin de ejemplo
Cdigo Java: Fichero Programa.java
public class Programa
{
public static void main (String[] args)
{
System.out.println("Hola");
}
}

Compilacin
javac Programa.java

Ejecucin
java Programa

Resultado

Introduccin a la Programacin: Java

- 17 -

Fernando Berzal

Applet de ejemplo
Cdigo Java: Fichero Saludo.java
import java.awt.*;
import java.applet.Applet;
public class Saludo extends Applet
{
public void paint(Graphics g) {
g.drawString("Hola!", 50, 50);
}
}

Pgina web: Fichero Saludo.html


<html>
<head>
<title>Applet bsico</title>
</head>
<body>
<applet code="Saludo" width=300 height=200>
</applet>
</body>
</html>

Resultado

Introduccin a la Programacin: Java

- 18 -

Fernando Berzal

Fases en la creacin y ejecucin de programas en Java


Fase I: Editor
Se crea un programa con la ayuda de un editor
Se almacena en un fichero con extensin .java
Fase II: Compilador
El compilador lee el cdigo Java (fichero .java)
Si se detectan errores sintcticos, el compilador nos informa de ello.
Se generan los bytecodes, que se almacenan en ficheros .class
Fase III: Cargador de clases
El cargador de clases lee los bytecodes (ficheros .class):
Los bytecodes pasan de disco a memoria principal.
Fase IV: Verificador de bytecodes
El verificador de bytecodes comprueba que los bytecodes son
vlidos y no violan las restricciones de seguridad de la mquina
virtual Java.
Fase V: Intrprete de bytecodes o compilador JIT
La mquina virtual Java (JVM) lee los bytecodes y los traduce al
lenguaje que el ordenador entiende (cdigo mquina).
NOTA:

Conforme se ejecuta el programa, se hace uso de la


memoria principal para almacenar los datos con los
que trabaja la aplicacin.

Introduccin a la Programacin: Java

- 19 -

Fernando Berzal

Caractersticas clave de Java

Java es multiplataforma
Los programas escritos en Java se compilan en un bytecode
independiente de la mquina y todos los sistemas operativos
principales tienen entornos de ejecucin de aplicaciones Java
[mquinas virtuales].
NOTA: La idea no es nueva (p.ej. UCSD Pascal)
Java es seguro
Pueden forzarse restricciones sobre las operaciones permitidas (los
applets no acceden directamente al hardware de la mquina).
Al cargar un programa en memoria, la mquina virtual Java verifica
los bytecodes de la aplicacin.
Java tiene un amplio conjunto de bibliotecas estndar
Bibliotecas para trabajar con colecciones y otras estructuras de
datos, ficheros, acceso a bases de datos (JDBC), interfaces grficas
de usuario (JFC/Swing), redes de ordenadores (RMI, Jini),
aplicaciones distribuidas (EJB), interfaces web (servlets/JSP),
hebras, compresin de datos, criptografa...

Introduccin a la Programacin: Java

- 20 -

Fernando Berzal

Java incluye una biblioteca portable


para la creacin de interfaces grficas de usuario
(AWT en Java 1.0/1.1 y JFC/Swing en Java 2).
Look & feel en funcin del sistema operativo:

Java simplifica algunos aspectos a la hora de programar


Gestin automtica de memoria (recolector de basura).
Comprobacin estricta de tipos
Sintaxis simplificada con respecto a C++.
o
o
o
o

No se manejan punteros explcitamente (todo son punteros en realidad).


No hay que crear makefiles (como en C/C++).
No hay que mantener ficheros de cabecera aparte (como en C/C++).
No existen macros (#define en C/C++), ya que son propensas a errores.

Introduccin a la Programacin: Java

- 21 -

Fernando Berzal

Mitos y realidades de Java


www.corewebprogramming.com
Mito: Java es un lenguaje de programacin para la web.
Realidad: Java es un lenguaje de programacin de propsito general.
Uso estimado de Java:
5% applets (clientes web)
45% aplicaciones de escritorio (PCs)
50% aplicaciones en el servidor (servlets/EJB)

Mito: Write once, run anywhere


Realidad: Se puede conseguir, aunque se debe comprobar.
Motivos: Las aplicaciones Java pueden ejecutar cdigo local
(nativo), las interfaces grficas pueden comportarse de forma
ligeramente distinta en distintas plataformas...

Mito: Java es un lenguaje interpretado.


Realidad: Los compiladores JIT compilan el programa al cargarlo.

Mito: La seguridad y la independencia de la mquina son gratis.


Realidad: Aplicaciones un 20% ms lentas que en C++.

Mito: Java acabar con X (donde X puede ser Microsoft, C++...)


Realidad: Siempre existen ventajas y desventajas.
Microsoft tiene su propia alternativa: la plataforma .NET
Determinadas aplicaciones es mejor escribirlas en otros lenguajes:
- Utilidades simples y eficientes en ANSI C,
- Sistemas complejos de altas prestaciones en C++,
- Aplicaciones para Windows con Visual Basic .NET o C#...
Introduccin a la Programacin: Java

- 22 -

Fernando Berzal

Datos y tipos de datos


Dato
Representacin formal de hechos, conceptos o instrucciones
adecuada para su comunicacin, interpretacin y procesamiento
por seres humanos o medios automticos.

Tipo de dato
Especificacin de un dominio (rango de valores) y de un conjunto
vlido de operaciones a los que normalmente los traductores
asocian un esquema de representacin interna propio.

Clasificacin de los tipos de datos


En funcin de quin los define:
Tipos de datos estndar
Tipos de datos definidos por el usuario
En funcin de su representacin interna:
Tipos de datos escalares o simples
Tipos de datos estructurados

Introduccin a la Programacin

- 23 -

Fernando Berzal

Codificacin de los datos en el ordenador


En el interior del ordenador, los datos se representan en binario.

El sistema binario slo emplea dos smbolos: 0 y 1


Un bit nos permite representar 2 smbolos diferentes: 0 y 1
Dos bits nos permiten codificar 4 smbolos: 00, 01, 10 y 11
Tres bits nos permiten codificar 8 smbolos distintos:
000, 001, 010, 011, 100, 101, 110 y 111
En general,
con N bits podemos codificar 2N valores diferentes
N

2N

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536

Si queremos representar X valores diferentes, necesitaremos N


bits, donde N es el menor entero mayor o igual que log2 X
Introduccin a la Programacin

- 24 -

Fernando Berzal

Representacin de datos de tipo numrico


Representacin posicional
Un nmero se representa mediante un conjunto de cifras,
cuyo valor depende de la cifra en s y de la posicin que
ocupa en el nmero

NMEROS ENTEROS
Ejemplo: Si utilizamos 32 bits para representar nmeros enteros,
disponemos de 232 combinaciones diferentes de 0s y 1s:
4 294 967 296 valores.
Como tenemos que representar nmeros negativos y el cero,
el ordenador ser capaz de representar
del 2 147 483 648 al +2 147 483 647.
Con 32 bits no podremos representar nmeros ms grandes.
2 147 483 647 + 1 = 2 147 483 648 !!!

NMEROS REALES (en notacin cientfica)


(+|) mantisa x 2exponente
El ordenador slo puede representar un subconjunto de los
nmeros reales (nmeros en coma flotante)
Las operaciones aritmticas con nmeros en coma flotante
estn sujetas a errores de redondeo.

Estndar IEEE 754


Precisin sencilla
(bit de signo + 8 bits exponente + 23 bits mantisa)
Precisin doble
(bit de signo + 11 bits exponente + 52 bits mantisa)
Introduccin a la Programacin

- 25 -

Fernando Berzal

Representacin de textos
Se escoge un conjunto de caracteres: alfabticos, numricos,
especiales (separadores y signos de puntuacin), grficos y
de control (por ejemplo, retorno de carro).
Se codifica ese conjunto de caracteres utilizando n bits.
Por tanto, se pueden representar hasta 2n smbolos distintos.
Ejemplos de cdigos normalizados

ASCII (American Standard Code for Information Interchange)


- ANSI X3.4-1968, 7 bits (128 smbolos)
- ISO 8859-1 = Latin-1, 8 bits (256 smbolos)

UNICODE, ISO/IEC 10646, 16 bits (65536 smbolos)

Introduccin a la Programacin

- 26 -

Fernando Berzal

Tipos de datos primitivos en Java


El lenguaje Java define 8 tipos de datos primitivos:
byte
float

short
double

int
char

long
boolean

Datos de tipo numrico


- Nmeros enteros
- Nmeros en coma flotante

byte, short, int, long

Datos de tipo carcter

char

Datos de tipo booleano

boolean

Introduccin a la Programacin: Java

- 27 -

float, double

Fernando Berzal

Nmeros enteros
byte, short, int, long

4 tipos bsicos para representar nmeros enteros (con signo):

Tipo
Espacio en
Valor
Valor
de dato memoria
mnimo
Mximo
byte
8 bits
-128
127
short
16 bits
-32768
32767
int
32 bits
-2147483648
2147483647
long
-9223372036854775808 9223372036854775807
64 bits
Literales enteros
Los literales enteros pueden expresarse:
- En decimal (base 10): 255
- En octal (base 8): 0377 ( 382 + 781 + 7 = 255 )
- En hexadecimal (base 16): 0xff ( 15*161 + 15 = 255)
Los literales enteros son de tipo int por defecto (entre -231 y 231-1).
Un literal entero es de tipo long si va acompaado del sufijo l o L:
1234567890L es de tipo long

NOTA:

Se prefiere el uso de L porque l


(L minscula) puede confundirse con 1 (uno).

Definicin
Literal: Especificacin de un valor concreto de un tipo de dato.
Introduccin a la Programacin: Java

- 28 -

Fernando Berzal

Operaciones con nmeros enteros


Desbordamiento
Si sobrepasamos el valor mximo que se puede representar con un
tipo de dato entero, nadie nos avisa de ello: en la ejecucin de
nuestro programa obtendremos un resultado incorrecto.
Tipo

Operacin
127 + 1
32767 + 1
2147483647 + 1

byte
short
int

Resultado
-128
-32768
-2147483648

Para obtener el resultado correcto, hemos de tener en cuenta el


rango de valores de cada tipo de dato, de tal forma que los
resultados intermedios de un clculo siempre puedan representarse
correctamente:
Tipo
int
long

Operacin
1000000 * 1000000
1000000 * 1000000

Resultado
-727379968
1000000000000

Divisin por cero


Si dividimos un nmero entero por cero,
se produce un error en tiempo de ejecucin:
Exception in thread "main"
java.lang.ArithmeticException: / by zero
at

La ejecucin del programa termina de forma


brusca al intentar hacer la divisin por cero.

Introduccin a la Programacin: Java

- 29 -

Fernando Berzal

Nmeros en coma flotante


float, double

Segn el estndar IEEE 754-1985

Tipo
Espacio en
Mnimo
Mximo
Dgitos
de dato memoria (valor absoluto) (valor absoluto) significativos
float
32 bits
1.4 x 10-45
3.4 x 1038
6
-324
308
double
64 bits
4.9 x 10
1.8 x 10
15
Literales reales
- Cadenas de dgitos con un punto decimal
123.45

0.0

.001

- En notacin cientfica (mantisa10exponente)


123e45

123E+45 1E-6

Por defecto, los literales reales representan valores de tipo double


Para representar un valor de tipo float, hemos de usar el sufijo f o F:
123.45F 0.0f

.001f

Operaciones con nmeros en coma flotante


Las operaciones aritmticas en coma flotante no generan
excepciones, aunque se realicen operaciones ilegales:
- Cuando el resultado de una operacin est fuera de rango, se
obtiene +Infinity o Infinity (infinito).
- Cuando el resultado de una operacin est indeterminado, se
obtiene NaN (Not a Number)
Operacin
1.0 / 0.0
-1.0 / 0.0
0.0 / 0.0
Introduccin a la Programacin: Java

Resultado
Infinity
-Infinity
NaN
- 30 -

Fernando Berzal

Operadores aritmticos
Java incluye cinco operadores para realizar operaciones aritmticas:
Operador

Operacin

+
*
/
%

Suma
Resta o cambio de signo
Multiplicacin
Divisin
Mdulo (resto de la divisin)

- Si los operandos son enteros, se realizan operaciones enteras.


- En cuanto uno de los operandos es de tipo float o double,
la operacin se realiza en coma flotante.
- No existe un operador de exponenciacin: para calcular xa hay
que utilizar la funcin Math.pow(x,a)

Divisin (/)
Operacin
7/3
7 / 3.0f
5.0 / 2
7.0 / 0.0
0.0 / 0.0

Tipo

Resultado

int
float
double
double
double

2
2.333333333f
2.5
+Infinity
NaN

- Si se dividen enteros, el resultado es entero y el resto se pierde.


- Una divisin entera por cero produce una excepcin.
- Una divisin por cero, en coma flotante, produce Infinite o NaN.
Mdulo (%): Resto de dividir
Operacin
7%3
4.3 % 2.1

Tipo

Resultado

int
double

Introduccin a la Programacin: Java

- 31 -

0.1
Fernando Berzal

Expresiones aritmticas
Se pueden combinar literales y operadores
para formar expresiones complejas.
Ejemplo

3 + 4 x 10( y 5)( a + b + c)
4 9+ x

+ 9( +
)
5
x
x
y
En Java se escribira as:
(3+4*x)/5 10*(y-5)*(a+b+c)/x + 9*(4/x + (9+x)/y)

- Las expresiones aritmticas se evalan de izquierda a derecha.


- Los operadores aritmticos mantienen el orden de precedencia
habitual (multiplicaciones y divisiones antes que sumas y restas).
- Para especificar el orden de evaluacin deseado, se utilizan
parntesis.
NOTA: Es recomendable utilizar parntesis para eliminar
interpretaciones errneas y posibles ambigedades

Precisin
Las operaciones en coma flotante no son exactas debido a la forma
en que se representan los nmeros reales en el ordenador
Operacin
1 - 0.1 - 0.1 - 0.1 - 0.1 - 0.1
1.0 - 0.9

Resultado
0.5000000000000001
0.09999999999999998

Definicin
Expresin: Construccin que se evala para devolver un valor.
Introduccin a la Programacin: Java

- 32 -

Fernando Berzal

Caracteres
char

http://www.unicode.org/

Tipo
Espacio en
de dato memoria
char
16 bits

Codificacin
UNICODE

Literales de tipo carcter


Valores entre comillas simples
a b c

1 2 3

Cdigos UNICODE (en hexadecimal): \u????


\u000a (avance de lnea)
\u000d (retorno de carro)
Secuencias de escape para representar caracteres especiales:
Secuencia
de escape
\t
\n
\r
\b
\
\
\\

Descripcin
Tabulador (tab)
Avance de lnea (new line)
Retorno de carro (carriage return)
Retroceso (backspace)
Comillas simples
Comillas dobles
Barra invertida

La clase Character define funciones (mtodos estticos)


para trabajar con caracteres:
isDigit(), isLetter(), isLowerCase(), isUpperCase()
toLowerCase(), toUpperCase()
Introduccin a la Programacin: Java

- 33 -

Fernando Berzal

Cadenas de caracteres
La clase String
- String no es un tipo primitivo, sino una clase predefinida
- Una cadena (String) es una secuencia de caracteres
- Las cadenas de caracteres, en Java, son inmutables: no se pueden
modificar los caracteres individuales de la cadena.

Literales
Texto entra comillas dobles
Esto es una cadena
Esto tambin es una cadena

Las secuencias de escape son necesarias para introducir


determinados caracteres dentro de una cadena:
\Esto es una cadena entre comillas\

Concatenacin de cadenas de caracteres


El operador + sirve para concatenar cadenas de caracteres
Operacin
"Total = " + 3 + 4
"Total = " + (3+4)

Resultado
Total = 34
Total = 7

Si cualquier operando es un String,


toda la operacin se convierte en una concatenacin de cadenas.
En Java, cualquier cosa puede convertirse automticamente en
una cadena de caracteres (un objeto de tipo String)

Introduccin a la Programacin: Java

- 34 -

Fernando Berzal

Datos de tipo booleano


boolean

Representan algo que puede ser verdadero (true) o falso (false)


Espacio en
memoria
boolean
1 bit

Valores
Verdadero o falso

Literales
Literal
true
false

Significado
Verdadero (1)
Falso (0)

Expresiones de tipo booleano


Se construyen a partir de expresiones de tipo numrico con
operadores relacionales.
Se construyen a partir de otras expresiones booleanas con
operadores lgicos o booleanos.

Operadores relacionales
- Operadores de comparacin vlidos para nmeros y caracteres
- Generan un resultado booleano
Operador
==
!=
<
>
<=
>=

Introduccin a la Programacin: Java

Significado
Igual
Distinto
Menor
Mayor
Menor o igual
Mayor o igual
- 35 -

Fernando Berzal

Operadores lgicos/booleanos
- Operandos booleanos.
- Tienen menos precedencia que los operadores de comparacin.
Operador Nombre
!
NOT
&&
AND
||
OR
^
XOR

Significado
Negacin lgica
y lgico
o inclusivo
o exclusivo

Tablas de verdad
X

!X

true
False

false
true

A&&B

A||B

A^B

false
false
true
true

false
true
false
true

false
false
false
true

false
true
true
True

false
True
True
False

- NOT (!) cambia el valor booleano.


- AND (&&) devuelve true si los dos son operandos son true.
No evala el segundo operando si el primero es false
- OR (||) devuelve false si los dos son false.
No evala el segundo operando si el primero es true
- XOR (^) devuelve true si los dos operandos son diferentes.
Con operandos booleanos es equivalente a !=
Ejemplos
Nmero x entre 0 y 10
Nmero x fuera del intervalo [0,10]
o bien
Introduccin a la Programacin: Java

- 36 -

(0 <= x) && (x <= 10)


!((0 <= x) && (x <= 10))
(0 > x) || (x > 10)
Fernando Berzal

Extra: Operadores a nivel de bits


- Se pueden utilizar a nivel de bits con nmeros enteros.
- No se pueden usar con datos de otro tipo (p.ej. reales).

Los operadores NOT (~), AND (&), OR(|) y XOR (^)


Si alguno de los operandos es de tipo long, el resultado es long.
Si no, el resultado es de tipo int.
- NOT (~) realiza el complemento a 1 de un nmero entero:
Cambia los 0s por 1s y viceversa
- AND(&), OR(|) y XOR(^) funcionan a nivel de bits como los
operadores booleanos AND (&&), OR(||) y XOR (^),
respectivamente.

Operacin
~10
10 & 1
10 & 2
10 & 3
10 | 1
10 | 2
10 | 3
10 ^ 1
10 ^ 2
10 ^ 3

A nivel de bits

Resultado

~000001010
(111110101)
000001010 & 00001
(000000000)
000001010 & 00010
(000000010)
000001010 & 00011
(000000010)
000001010 | 00001
(000001011)
000001010 | 00010
(000001010)
000001010 | 00011
(000001011)
000001010 ^ 00001
(000001011)
000001010 ^ 00010
(000001000)
000001010 ^ 00011
(000001001)

-11

Introduccin a la Programacin: Java

- 37 -

0
2
2
11
10
11
11
8
9

Fernando Berzal

Los operadores de desplazamiento <<, >> y >>>


- El operador de desplazamiento a la izquierda (<<) desplaza los
bits del primer operando tantas posiciones a la izquierda como
indica el segundo operando. Los nuevos bits se rellenan con
ceros.
- El operador de desplazamiento a la derecha con signo (>>)
desplaza los bits del primer operando tantas posiciones a la
derecha como indica el segundo operando. Los nuevos bits se
rellenan con unos (si el primer operando es negativo) y con ceros
(si es positivo).
- El operador de desplazamiento a la derecha sin signo (>>>)
desplaza los bits del primer operando tantas posiciones a la
derecha como indica el segundo operando. Los nuevos bits se
rellenan siempre con ceros. Se pierde el signo del nmero.

Operacin
10 << 1
7 << 3
10 >> 1
27 >> 3
-50 >> 2
-50 >>> 2
0xff >>> 4

A nivel de bits

Resultado

00001010 << 1
(0010100)
00000111 << 3
(00111000)
00001010 >> 1
(00000101)
00011011 >> 3
(0000011)
11001110 >> 2
(11110011)
111001110 >>> 2
(001110011)
11111111 >>> 4
(00001111)

20
(==10*2)
56
(==7*23)
5
(==10/2)
3
(==27/23)
-13
(!=-50/22)
1073741811
15
(==255/24)

x<<b es equivalente a multiplicar por 2

x>>b y x>>>b son equivalentes

a realizar una divisin entera entre 2b cuando x es positivo


Introduccin a la Programacin: Java

- 38 -

Fernando Berzal

Variables
Una variable no es ms que un nombre simblico que identifica
una direccin de memoria:

Suma el contenido de la posicin 3001 y la 3002 y lo almacenas en la posicin 3003


vs.

total = cantidad1 + cantidad2


Suma cantidad1 y cantidad2 y lo almacenas en total

Declaracin de variables
Para usar una variable en un programa hay que declararla.
- El ordenador conoce as cmo codificar la informacin que se
va a almacenar en la posicin de memoria correspondiente.
- Al declarar una variable, se reserva el espacio de memoria
necesario para almacenar un valor del tipo de la variable.
- El identificador asociado a la variable se puede utilizar para
acceder al dato almacenado en memoria y para modificarlo.
Introduccin a la Programacin

- 39 -

Fernando Berzal

Declaracin de variables en Java


<tipo> identificador;
<tipo> lista de identificadores;

Las variables se han de declarar antes de poder usarlas.


Los identificadores de las variables son los nombres que
utilizaremos para referirnos a ellas.
Al declarar una variable, hay que definir su tipo: la variable
slo admitir valores del tipo especificado.
En una misma declaracin se pueden declarar varias variables,
siempre que sean del mismo tipo. En este caso, los
identificadores de las variables se separan por comas.

Ejemplos
// Declaracin una variable entera x de tipo int
int x;

// Declaracin de una variable real r de tipo double


double r;

// Declaracin de una variable c de tipo char


char c;

// Mltiples declaraciones en una sola lnea


int i, j, k;

Introduccin a la Programacin: Java

- 40 -

Fernando Berzal

Identificadores en Java
El primer smbolo del identificador ser un carcter
alfabtico (a, , z, A, , Z, _, $) pero no un dgito.
Despus de ese primer carcter, podremos poner caracteres
alfanumricos (a, , z) y (0, 1, , 9), signos de dlar $ o
guiones de subrayado _.
Los identificadores no pueden coincidir con las palabras
reservadas, que ya tienen significado en Java:
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

cast
operator

future
outer

generic
rest

inner
var

switch
synchronized
this
threadsafe
throw[s]
transient
true
try
void
while

Las maysculas y las minsculas se consideran diferentes.


$ y _ se interpretan como una letra ms.
$ no se suele utilizar en la prctica (lo usa el compilador).
Ejemplos vlidos
a, pepe, r456, tu_re_da, AnTeNa, antena, usd$

Ejemplos no vlidos
345abc, mi variable, Nombre.Largo, caada, camin

Java es un lenguaje sensible a maysculas/minsculas.


Introduccin a la Programacin: Java

- 41 -

Fernando Berzal

Convenciones
Los identificadores deben ser descriptivos: deben hacer
referencia al significado de aquello a lo que se refieren.
int n1, n2;
int anchura, altura;

// MAL
// BIEN

Los identificadores asociados a las variables se suelen poner


en minsculas.
int CoNTaDoR;
int contador;

// MAL
// BIEN

Cuando el identificador est formado por varias palabras, la


primera palabra va en minsculas y el resto de palabras se
inician con una letra mayscula.
int mayorvalor;
int mayor_valor;
int mayorValor;

// MAL
// ACEPTABLE
// MEJOR

Inicializacin de las variables


En una declaracin, las variables se pueden inicializar:
int i = 0;
float pi = 3.1415927f;
double x = 1.0, y = 1.0;

NOTA:

La inicializacin puede consistir en una expresin


compleja que se evala cuando se ejecuta el programa.

Introduccin a la Programacin: Java

- 42 -

Fernando Berzal

Definicin de constantes en Java


Una constante hace referencia a un valor que no puede modificarse
final <tipo> identificador = <valor>;

Las constantes se definen igual que cuando se declara una


variable y se inicializa su valor.
Con la palabra reservada final se impide la modificacin del
valor almacenado
Convenciones
Los identificadores asociados a las constantes se suelen
poner en maysculas.
final double PI = 3.141592;

Si el identificador est formado por varias palabras, las


distintas palabras se separan con un guin de subrayado
final char RETORNO_DE_CARRO = \n;
final double ELECTRONIC_CHARGE = 1.6E-19;

Si intentsemos modificar el valor de una constante,


el compilador nos dara un error:
RETORNO_DE_CARRO = \r;

// Ilegal

produce el siguiente error


Cannot assign a value to final variable RETORNO_DE_CARRO
Introduccin a la Programacin: Java

- 43 -

Fernando Berzal

Expresiones y sentencias
Expresin
Construccin (combinacin de tokens)
que se evala para devolver un valor.

Sentencia
Representacin de una accin o una secuencia de acciones.
En Java, todas las sentencias terminan con un punto y coma [;].

Construccin de expresiones
Literales y variables son expresiones primarias:
1.7
sum

// Literal real de tipo double


// Variable

- Los literales se evalan a s mismos.


- Las variables se evalan a su valor.
Los operadores nos permiten combinar expresiones primarias y
otras expresiones formadas con operadores:
1 + 2 + 3*1.2 + (4 +8)/3.0

Los operadores se caracterizan por:


- El nmero de operandos (unarios, binarios o ternarios).
- El tipo de sus operandos (p.ej. numricos o booleanos).
- El tipo del valor que generan como resultado.
Introduccin a la Programacin: Java

- 44 -

Fernando Berzal

Nmero de operandos
- Operadores unarios
Operador

Descripcin
Cambio de signo
Operador NOT
Complemento a 1

!
~

- Operadores binarios
Operadores
+ - * / %
== != < >
<= >=
&& || ^
& | ^
<< >> >>>
+

Descripcin
Operadores aritmticos
Operadores relacionales
Operadores booleanos
Operadores a nivel de bits
Concatenacin de cadenas

Tipo de los operandos


Operadores
+ - * / %
== !=
< > <= >=
&& || ^
~ & | ^
<< >> >>>
+

Descripcin
Operadores aritmticos
Operadores de igualdad

Operadores booleanos

Operandos
Nmeros
Cualesquiera
Nmeros
o caracteres
Booleanos

Operadores a nivel de bits

Enteros

Concatenacin de cadenas

Cadenas

Descripcin
Operadores aritmticos

Resultado
Nmero*

Operadores de comparacin

Tipo del resultado


Operadores
+ - * / %
== != < >
<= >=
&& || ^
~ & | ^
<< >> >>>
+

Operadores relacionales

Booleano

Operadores booleanos
Operadores a nivel de bits

Entero

Concatenacin de cadenas

Cadena

Introduccin a la Programacin: Java

- 45 -

Fernando Berzal

Sentencias de asignacin
Las sentencias de asignacin constituyen el ingrediente bsico en la
construccin de programas con lenguajes imperativos.

Sintaxis:
<variable> = <expresin>;

Al ejecutar una sentencia de asignacin:


1. Se evala la expresin que aparece a la derecha del operador de
asignacin (=).
2. El valor que se obtiene como resultado de evaluar la expresin
se almacena en la variable que aparece a la izquierda del
operador de asignacin (=).

Restriccin:
El tipo del valor que se obtiene como resultado de evaluar la
expresin ha de ser compatible con el tipo de la variable.

Ejemplos
x = x + 1;

// Declaracin con inicializacin


otraVariable = miVariable; // Sentencia de asignacin
int miVariable = 20;

NOTA IMPORTANTE:
Una sentencia de asignacin no es una igualdad matemtica.
Introduccin a la Programacin: Java

- 46 -

Fernando Berzal

Efectos colaterales
Al evaluar una expresin, algunos operadores provocan efectos
colaterales (cambios en el estado del programa; es decir, cambios en
el valor de alguna de las variables del programa).

Operadores de incremento (++) y decremento (--)


El operador ++ incrementa el valor de una variable.
El operador -- decrementa el valor de una variable.
El resultado obtenido depende de la posicin relativa del operando:
Operador
x++
++x
x---x

Descripcin
Post-incremento
Evala primero y despus incrementa
Pre-incremento
Primero incrementa y luego evala
Post-decremento
Evala primero y luego decrementa
Pre-decremento
Primero decrementa y luego evala

Ejemplo

Equivalencia

Resultado

i=0; i++;
i=1; j=++i;
i=1; j=i++;
i=3; n=2*(++i);
i=3; n=2*(i++);
i=1; k=++i+i;

i=0; i=i+1;
i=1; i=i+1; j=i;
i=1; j=i; i=i+1;
i=3; i=i+1; n=2*i;
i=3; n=2*i; i=i+1;
i=1; i=i+1; k=i+i;

i=1;
j=2;
j=1;
n=8;
n=6;
k=4;

El uso de operadores de incremento y decremento reduce el tamao


de las expresiones pero las hace ms difciles de interpretar. Es mejor
evitar su uso en expresiones que modifican mltiples variables o
usan varias veces una misma variable.

Introduccin a la Programacin: Java

- 47 -

Fernando Berzal

Operadores combinados de asignacin (op=)


Java define 11 operadores que combinan el operador de asignacin
con otros operadores (aritmticos y a nivel de bits):
Operador
+=
-=
*=
/=
%=
&=
|=
^=
<<=
>>=
>>>=

Ejemplo

Equivalencia

i
f
n
n
n
k
k
k
x
x
x

i++;
f = f
n = n
n = n
n = n
k = k
k = k
k = k
x = x
x = x
x = x

+= 1;
-= 4.0;
*= 2;
/= 2;
%= 2;
&= 0x01;
|= 0x02;
^= 0x04;
<<= 1;
>>= 2;
>>>= 3;

4.0;
* 2;
/ 2;
% 2;
& 0x01;
& 0x02;
& 0x04;
<< 1;
>> 2;
>>> 3;

El operador += tambin se puede utilizar con cadenas de caracteres:


Ejemplo

Resultado

cadena = Hola;
cadena = Hola,;
cadena += ,
nombre = Juan;
apellido = Q.;
nombre += +apellido; nombre = Juan Q.

La forma general de los operadores combinados de asignacin es


variable op= expresin;

que pasa a ser


variable = variable op (expresin);

OJO: v[i++]+= 2; y v[i++]=v[i++]+2; no son equivalentes.


Introduccin a la Programacin: Java

- 48 -

Fernando Berzal

Conversin de tipos
En determinadas ocasiones, nos interesa convertir el tipo de un dato
en otro tipo para poder operar con l.
Ejemplo
Convertir un nmero entero en un nmero real
para poder realizar divisiones en coma flotante
Java permite realizar conversiones entre datos de tipo numrico
(enteros y reales), as como trabajar con caracteres como si fuesen
nmeros enteros:
- La conversin de un tipo con menos bits a un tipo con ms bits es
automtica (vg. de int a long, de float a double), ya que el
tipo mayor puede almacenar cualquier valor representable con el
tipo menor (adems de valores que no caben en el tipo menor).
- La conversin de un tipo con ms bits a un tipo con menos bits
hay que realizarla de forma explcita con castings. Como se
pueden perder datos en la conversin, el compilador nos obliga a
ser conscientes de que se est realizando una conversin
int i;
byte b;
i = 13;

// No se realiza conversin alguna

b = 13;

// Se permite porque 13 est dentro


// del rango permitido de valores

b = i;

// No permitido (incluso aunque


// 13 podra almacenarse en un byte)

b = (byte) i;

// Fuerza la conversin

i = (int) 14.456;

// Almacena 14 en i

i = (int) 14.656;

// Sigue almacenando 14

Introduccin a la Programacin: Java

- 49 -

Fernando Berzal

Castings
Para realizar una conversin explcita de tipo (un casting) basta
con poner el nombre del tipo deseado entre parntesis antes del valor
que se desea convertir:
char c;
int x;
long k;
double d;

Sin conversin de tipo:


c
x
k
d

=
=
=
=

A;
100;
100L;
3.0;

Conversiones implcitas de tipo (por asignacin):


x
k
k
d

=
=
=
=

c;
100;
x;
3;

//
//
//
//

char int
int long
int long
int double

Conversiones implcitas de tipos (por promocin aritmtica)


c+1
x / 2.0f

// char int
// int float

Errores de conversin (detectados por el compilador):


x = k;
x = 3.0;
x = 5 / 2.0f;

// long int
// double int
// float int

Conversiones explcitas de tipo (castings):


x = (int) k;
x = (int) 3.0;
x = (int) (5 / 2.0f);

Introduccin a la Programacin: Java

- 50 -

Fernando Berzal

Tabla de conversin de tipos

boolean

byte

short

char

int

long

Float

double

Convertir desde

Convertir a

boolean

byte

Short

char

int

I*

long

I* I*

float

double

No se puede realizar la conversin


(boolean no se puede convertir a otro tipo)

Conversin implcita
(se realiza de forma automtica)

I*

Conversin implcita
(con posible prdida de dgitos significativos)

Conversin explcita
(requiere la realizacin de un casting)

El compilador de Java comprueba siempre los tipos de las


expresiones y nos avisa de posibles errores:
Incompatible types (N) y Possible loss of precision (C)
Introduccin a la Programacin: Java

- 51 -

Fernando Berzal

Algunas conversiones de inters


De nmeros en coma flotante a nmeros enteros
Al convertir de nmero en coma flotante a entero,
el nmero se trunca (redondeo a cero).
En la clase Math existen funciones
que nos permiten realizar el redondeo de otras formas:
Math.round(x), Math.floor(x), Math.ceil(x)

Conversin entre caracteres y nmeros enteros


Como cada carcter tiene asociado un cdigo UNICODE,
los caracteres pueden interpretarse como nmeros enteros sin signo
int i;
char c;

Ejemplo
I
c
c
C

=
=
=
=

Equivalencia

Resultado

a;
i = (int) a;
97;
c = (char) 97;
a+1; c = (char) ((int)a+1);
(char)(i+2);

i
c
c
c

=
=
=
=

97
a
b
c

Conversin de cadenas de texto en datos del tipo adecuado


Cuando leemos un dato desde el teclado, obtenemos una cadena de
texto (un objeto de tipo String) que deberemos convertir en un dato
del tipo adecuado utilizando las siguientes funciones auxiliares:
b
s
i
n

=
=
=
=

Byte.parseByte(str);
Short.parseShort(str);
Integer.parseInt(str);
Long.parseLong(str);

//
//
//
//

String
String
String
String

byte
short
int
long

f = Float.parseFloat(str);
// String float
d = Double.parseDouble(str); // String double
Introduccin a la Programacin: Java

- 52 -

Fernando Berzal

Evaluacin de expresiones
- La precedencia de los operadores determina el orden de
evaluacin de una expresin (el orden en que se realizan las
operaciones):
3*4+2 es equivalente a (3*4)+2
porque el operador * es de mayor precedencia que el operador +

- Cuando en una expresin aparecen dos operadores con el mismo


nivel de precedencia, la asociatividad de los operadores
determina el orden de evaluacin.
a b + c d es equivalente a ((a b) + c) d
porque los operadores aritmticos
son asociativos de izquierda a derecha
a = b += c = 5 es equivalente a a = (b += (c = 5))
porque los operadores de asignacin
son asociativos de derecha a izquierda

- La precedencia y la asociatividad determinan el orden de los


operadores, pero no especifican el orden en que se evalan los
operandos de un operador binario (un operador con dos
operandos):
En Java, los operandos se evalan de izquierda a derecha:
el operando de la izquierda se evala primero.
Si los operandos no tienen efectos colaterales (esto es, no cambian
el valor de una variable), el orden de evaluacin de los operandos
es irrelevante. Sin embargo, las asignaciones n=x+(++x); y
n=(++x)+x; generan resultados diferentes.

NOTA: Siempre es recomendable el uso de parntesis.


Los parntesis nos permiten especificar el orden de evaluacin de
una expresin, adems de hacer su interpretacin ms fcil.
Introduccin a la Programacin: Java

- 53 -

Fernando Berzal

Programas
Estructura de un programa simple
Los programas ms simples escritos en lenguajes imperativos
suelen realizar tres tareas de forma secuencial:
Entrada de datos
Procesamiento de los datos
Salida de resultados

El punto de entrada de un programa en Java es la funcin main:


public static void main (String[] args)
{

Declaraciones y sentencias escritas en Java


}

En realidad, Java es un lenguaje de programacin orientada a


objetos y todo debe estar dentro de una clase, incluida la funcin
main, tal como muestra el siguiente programa
public class MiPrimerPrograma
{
public static void main (String args[])
{
System.out.println("Mensaje por pantalla);
}
}

Las llaves {} delimitan bloques en Java


(conjuntos de elementos de un programa).
La mquina virtual Java ejecuta el programa
invocando a la funcin main.
Introduccin a la Programacin: Java

- 54 -

Fernando Berzal

Operaciones bsicas de entrada/salida


Mostrar resultados con la funcin System.out.println
La funcin System.out.println nos permite mostrar una lnea
de texto en la pantalla cuando ejecutamos el programa:
int edad = 25;
System.out.println(Tengo + edad + aos);
final double pi = 3.1415927;
System.out.println(Valor de PI = + pi);

En la funcin println se suele utilizar el operador + para


concatenar cadenas de caracteres.
Cualquier cosa en Java se puede convertir en una cadena.
Obtener datos de entrada a travs de los parmetros de main
La funcin main puede recibir parmetros:
public class Eco
{
public static void main (String[] args)
{
System.out.println(args[0]);
System.out.println(args[1]);
}
}
Si ejecutamos el programa Eco
java Eco dato1 dato2

obtenemos como salida


dato1
dato2

Los parmetros de la funcin main son de tipo String, por lo


que deberemos convertir las cadenas en datos del tipo deseado.
Con args.length podemos saber cuntos parmetros se le
han pasado a nuestro programa.
Introduccin a la Programacin: Java

- 55 -

Fernando Berzal

Leer datos desde el teclado en Java


En Java, la realizacin de operaciones de entrada de datos no es
inmediata, por lo que utilizaremos una clase auxiliar que se
encargar de realizar las operaciones necesarias:
b
s
i
k

=
=
=
=

TextIO.getByte();
TextIO.getShort();
TextIO.getInt();
TextIO.getLong();

x = TextIO.getFloat();
y = TextIO.getDouble();

//
//
//
//

byte
short
int
long

// float
// double

a = TextIO.getBoolean(); // boolean
c = TextIO.getChar();

// char

s = TextIO.getln();

// String

Internamente, la implementacin de la clase auxiliar TextIO


realiza algo similar a lo siguiente:
InputStreamReader input;
BufferedReader lector;
String cadena;
// Secuencia de bytes Secuencia de caracteres
input = new InputStreamReader(System.in);
// Secuencia de caracteres Secuencia de lneas
lector = new BufferedReader(input);
try {
cadena = lector.readLine();
} catch (Exception e) {
cadena = "";
}
// Y ahora hacemos lo que queramos con la cadena

Cuando estudiemos el uso de ficheros en Java comprenderemos


exactamente qu es lo que se hace al leer datos desde el teclado.
Introduccin a la Programacin: Java

- 56 -

Fernando Berzal

E/S con interfaces grficas de usuario (GUIs): JOptionPane


La biblioteca de clases estndar de Java incluye una amplia gama
de componentes para la construccin de interfaces grficas de
usuario.
El componente javax.swing.JOptionPane se puede emplear
para obtener datos de entrada y mostrar mensajes de salida:

Entrada de datos con showInputDialog


String entrada;
entrada = JOptionPane.showInputDialog
( "Introduzca un valor" );

entrada = JOptionPane.showInputDialog ( null,


"Introduzca un valor",
"Mi programa en Java",
JOptionPane.QUESTION_MESSAGE );

entrada = JOptionPane.showInputDialog ( null,


"Introduzca un valor",
"Otro programa en Java",
JOptionPane.INFORMATION_MESSAGE );

Introduccin a la Programacin: Java

- 57 -

Fernando Berzal

Salida de datos con showMessageDialog


JOptionPane.showMessageDialog ( null,
Bienvenido a Java! );

JOptionPane.showMessageDialog ( null,
Bienvenido a Java!,
Programa de ejemplo,
JOptionPane.INFORMATION_MESSAGE );

JOptionPane.showMessageDialog ( null,
Bienvenido a Java!,
Programa de ejemplo,
JOptionPane.WARNING_MESSAGE );

JOptionPane.showMessageDialog ( null,
Bienvenido a Java!,
Programa de ejemplo,
JOptionPane.ERROR_MESSAGE );

Cuando se emplea JOptionPane es aconsejable llamar a


System.exit(0); para terminar la ejecucin del programa.
Introduccin a la Programacin: Java

- 58 -

Fernando Berzal

Ejemplos
Calificacin final de la asignatura
public class Asignatura
{
public static void main (String args[])
{
// Declaraciones
// Constante
final double PORCENTAJE_LABORATORIO = 0.5;
// Variables
String nombre;
double notaExamen;
double notaLaboratorio;
double notaFinal;
// Entrada de datos
nombre = args[0];
notaExamen = Double.parseDouble(args[1]);
notaLaboratorio = Double.parseDouble(args[2]);
// Clculo
notaFinal =
(1-PORCENTAJE_LABORATORIO)*notaExamen
+ PORCENTAJE_LABORATORIO*notaLaboratorio;
// Salida de resultados
System.out.println (nombre
+ " ha obtenido una nota final de "
+ notaFinal);
}
}

Ejecucin del programa


java Asignatura Pepe 6 9
Pepe ha obtenido una nota final de 7.5
java Asignatura Juan Nadie 8 9.5
Juan Nadie ha obtenido una nota final de 8.75
Introduccin a la Programacin: Java

- 59 -

Fernando Berzal

Ejemplos
Ao bisiesto
Programa para comprobar si un ao es bisiesto o no:
Un ao es bisiesto si es divisible por 4 pero no por 100,
o bien es divisible por 400.
public class Bisiesto
{
public static void main (String args[])
{
// Declaracin de variables
int
year;
boolean bisiesto;
// Entrada de datos
year = Integer.parseInt(args[0]);
// Clculos
bisiesto = ((year%4==0) && (year%100!=0))
|| (year%400==0);
// Salida de resultados
System.out.println(bisiesto);
}
}

Ejecucin del programa


java Bisiesto 2004
true
java Bisiesto 2005
false
java Bisiesto 2000
true
java Bisiesto 2100
false
Introduccin a la Programacin: Java

- 60 -

Fernando Berzal

Ejemplos
Cuota de una hipoteca
import javax.swing.JOptionPane;
public class Hipoteca
{
public static void main (String args[])
{
double cantidad; // en euros
double interes; // en porcentaje (anual)
int
tiempo;
// en aos
double cuota;
// en euros (mensual)
double interesMensual; // en tanto por uno
String entrada;
// variable auxiliar
// Entrada de datos
entrada = JOptionPane.showInputDialog
("Importe de la hipoteca ()");
cantidad = Double.parseDouble(entrada);
entrada = JOptionPane.showInputDialog
("Tipo de inters (%)");
interes = Double.parseDouble(entrada);
entrada = JOptionPane.showInputDialog
("Perodo de amortizacin (aos)");
tiempo = Integer.parseInt(entrada);
// Clculo de la cuota mensual
interesMensual = interes/(12*100);
cuota = (cantidad*interesMensual)
/ (1.01.0/Math.pow(1+interesMensual,tiempo*12));
cuota = Math.round(cuota*100)/100.0;
// Resultado
JOptionPane.showMessageDialog
(null, "Cuota mensual = "+cuota+"" );
System.exit(0);
}
}
Introduccin a la Programacin: Java

- 61 -

Fernando Berzal

Ejecucin del programa


1. Datos de entrada

2. Clculo de la cuota mensual


intersMensual () = intersAnual / 12
cuotaMensual =

cantidad
1
1
(1 + ) aos12

Redondeo
Operacin

Descripcin
Resultado
100*cuota
double
Cuota en cntimos de euro
Math.round() Redondeo al entero ms cercano
int
/ 100.0
Cuota en euros (con cntimos) double

3. Resultado final

Introduccin a la Programacin: Java

- 62 -

Fernando Berzal

Estilo y documentacin del cdigo


Comentarios
Los comentarios sirven para incluir aclaraciones en el cdigo.
Java permite dos tipos de comentarios:
// Comentarios de una lnea
/* Comentarios de varias lneas */

Es bueno incluir comentarios que expliquen lo que hace el


programa y sus caractersticas claves (p.ej. autor, fecha,
algoritmos utilizados, estructuras de datos, peculiaridades).
// Clculo del MCD
// usando el algoritmo de Euclides
// Fernando Berzal, 2004

Los comentarios nunca han de limitarse a decir en lenguaje


natural lo que ya est escrito en el cdigo: Jams se utilizarn
para parafrasear el cdigo y repetir lo que es obvio.
i++;

// Incrementa el contador

Los comentarios han de aclarar; esto es, ayudar al lector en las


partes difciles (y no confundirle). Si es posible, escriba cdigo
fcil de entender por s mismo: cuanto mejor lo haga, menos
comentarios necesitar.
int mes;

// Mes

int mes;

// Mes del ao (1..12)

ax = 0x723;

/* RIP L.v.B. */

NB: Beethoven muri en 1827 (0x723 en hexadecimal).


Introduccin a la Programacin: Java

- 63 -

Fernando Berzal

Sangras
Conviene utilizar espacios en blanco o separadores para delimitar
el mbito de las estructuras de control de nuestros programas.
Lneas en blanco
Para delimitar claramente los distintos segmentos de cdigo en
nuestros programas dejaremos lneas en blanco entre ellos.
Identificadores
Los identificadores deben ser descriptivos (reflejar su significado).

p, i, s...

precio, izquierda, suma...

Declaraciones
Usualmente, declararemos una nica variable por lnea.
Nunca mezclaremos en una misma lnea la declaracin de
variables que sean de distintos tipos o que se utilicen en el
programa para distintos fines.
Constantes
Se considera una mala costumbre incluir literales de tipo
numrico (nmeros mgicos) en medio del cdigo. Se
prefiere la definicin de constantes simblicas (declaraciones
con final).

Introduccin a la Programacin: Java

- 64 -

Fernando Berzal

Expresiones
Uso de parntesis: Aunque las normas de precedencia de los
operadores vienen definidas en el lenguaje, no abusaremos de
ellas. Siempre resulta ms fcil interpretar una expresin si sta
tiene los parntesis apropiados. Adems, stos eliminan
cualquier tipo de ambigedad.
Uso de espacios en blanco: Resulta ms fcil leer una
expresin con espacios que separen los distintos operadores y
operandos involucrados en la expresin.
a%x*c/b-1

( (a%x) * c ) / b - 1

Expresiones booleanas: Es aconsejable escribirlas como se


diran en voz alta.
!(bloque<actual)

( bloque >= actual )

Expresiones complejas:
Es aconsejable dividirlas para mejorar su legibilidad
Claridad:
Siempre buscaremos la forma ms simple de escribir una expresin.
key = key >> ( bits ((bits>>3)<<3));
key >>= bits & 0x7;

Conversiones de tipo (castings):


Evitaremos las conversiones implcitas de tipo. Cuando
queramos realizar una conversin de tipo, lo indicaremos
explcitamente.
i = (int) f;

Siempre se han de evitar los efectos colaterales


(modificaciones no deseadas pueden afectar a la ejecucin del
programa sin que nos demos cuenta de ello).
Introduccin a la Programacin: Java

- 65 -

Fernando Berzal

IDEA CLAVE
Escribimos cdigo para que lo puedan leer otras personas,
no slo para que lo traduzca el compilador (si no fuese as,
podramos seguir escribiendo nuestros programas en binario).

No comente el cdigo malo (uso de construcciones extraas,


expresiones confusas, sentencias poco legibles...): Reescrbalo.
No contradiga al cdigo: Los comentarios suelen coincidir con
el cdigo cuando se escriben, pero a medida que se corrigen
errores y el programa evoluciona, los comentarios suelen
dejarse en su forma original y aparecen discrepancias. Si
cambia el cdigo, asegrese de que los comentarios sigan
siendo correctos.

El cdigo bien escrito


es ms fcil de leer, entender y mantener
(adems, seguramente tiene menos errores)

Errores de programacin
Errores sintcticos
Errores detectados por el compilador en tiempo de compilacin.
Errores semnticos
Slo se detectan en tiempo de ejecucin: Causan que el programa
finalice inesperadamente su ejecucin (p.ej. divisin por cero) o
que el programa proporcione resultados incorrectos.
Introduccin a la Programacin: Java

- 66 -

Fernando Berzal

Elementos lxicos
del lenguaje de programacin
Java
Elementos lxicos del lenguaje de programacin Java
Palabras reservadas
Identificadores
Literales
Operadores
Delimitadores
Comentarios
Apndices
Operadores de Java
Sintaxis de Java

Elementos lxicos de Java


Token
Componente lxico de un lenguaje de programacin

Palabras reservadas
Palabras que tiene un significado concreto en el lenguaje de programacin,
sin necesidad de que se lo asignemos nosotros.
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

cast
operator

future
outer

generic
rest

inner
var

switch
synchronized
this
threadsafe
throw[s]
transient
true
try
void
while

Identificadores
Palabras que podemos utilizar para denominar algo en el lenguaje.
Identificadores en Java
- El primer smbolo del identificador ser un carcter alfabtico (a, , z,
A, , Z, _, $) pero no un dgito. Despus de ese primer carcter,
podremos poner caracteres alfanumricos (a, , z) y (0, 1, , 9),
signos de dlar $ o guiones de subrayado _.
- Los identificadores no pueden coincidir con las palabras reservadas.
- Las maysculas y las minsculas se consideran diferentes.
- El signo de dlar y el guin de subrayado se interpretan como una letra
ms.
Ejemplos vlidos
a, pepe, r456, tu_re_da, AnTeNa, antena, usd$
Ejemplos no vlidos
345abc, mi variable, Nombre.Largo, caada, camin
Elementos lxicos de Java

-1-

Fernando Berzal

Literal
Especificacin de un valor concreto de un tipo de dato.
Nmeros enteros
21 (int), 21L (long), 077 (en octal), 0xDC00 (en hexadecimal)
Nmeros reales
3.14 (double), 3.14f (float), 3.14d (double), 2e12, 3.1E12
Valores booleanos
true (verdadero), false (falso)
Caracteres
p, \u???? (cdigo UNICODE en hexadecimal), \t (tabulador)
Cadenas de caracteres
mensaje, (cadena vaca)

Operadores
Igual que en Matemticas, realizan una accin especfica:
- Suelen estar definidos en el ncleo del compilador
(aunque tambin pueden estar definidos en bibliotecas externas)
- Suelen representarse con tokens formados por smbolos.
- Suelen utilizar notacin infija.
- Pueden aplicarse a uno o varios operandos (argumentos).
- Suelen devolver un valor.
Operadores en Java, por orden de precedencia
. [ ] ( )
++ -! ~ instanceof
new
* / %
+ << >> >>>
< > <= >= == !=
& ^ |
&& ||
? :
= op= ,
Elementos lxicos de Java

-2-

Fernando Berzal

Delimitadores
Smbolos utilizados como separadores de las distintas construcciones de un
lenguaje de programacin (esto es, los signos de puntuacin de un lenguaje
de programacin.
( ) PARNTESIS: Listas de parmetros en la definicin y llamada a
mtodos, precedencia en expresiones, expresiones para control
de flujo y conversiones de tipo.
{ } LLAVES: Inicializacin de arrays, bloques de cdigo, clases,
mtodos y mbitos locales.
[ ] CORCHETES: Arrays.
;

PUNTO Y COMA: Separador de sentencias.

COMA: Identificadores consecutivos en una declaracin de


variables y sentencias encadenadas dentro de una sentencia for.

PUNTO: Separador de nombres de paquetes, subpaquetes y


clases; separador entre variables y mtodos/miembros.

Comentarios
Aclaracin que el programador incluye en el texto del programa para
mejorar su inteligibilidad.
En Java hay tres tipos de comentarios:
// Comentario de una sola lnea
/* Comentario de una o ms lneas */
/** Comentario de documentacin, una o ms lneas */

La herramienta javadoc genera automticamente en


HTML la documentacin del cdigo a partir de los
comentarios /** */
Elementos lxicos de Java

-3-

Fernando Berzal

Apndices
P
15

12

A Operador
I .
[]
( args )
++, - D ++,- +,~
!
D new
( type )
I * ,/, %

Operando(s)
Objeto, mtodo (miembro)
Array (indice)
Mtodo, lista de
argumentos variable
Variable
Nmero
Entero
Booleano
Clase, lista de argumentos
Tipo, cualquier tipo
Nmero, nmero

11

Numero, nmero
String, cualquiera
Entero, entero
Entero, entero
Entero, entero
Nmero, Nmero
Nmero, Nmero
Referencia, tipo
Primitiva , primitiva
Primitiva , primitiva
Referencia, referencia
Referencia, referencia
Entero, entero
Booleano, booleano
Entero, Entero
Booleano, Booleano
Entero, Entero
Booleano, Booleano
Booleano, Booleano
Booleano, Booleano
Booleano, otro, otro
Variable, otro

14

13

10
9
8

7
6
5
4
3
2
1

+,+
I <<
>>
>>>
I <, <=
>, >=
instance of
I ==
!=
==
!=
I &
&
I ^
^
I |
|
I &&
I ||
D ?:
D =
*=,/=,%=
+=,-=
,<<=,>>=
>>>=,
&=,^=,|=

Operacin
Acceso a un miembro del objeto
Acceso a un elemento de un array
Llamada a un mtodo
Post incremento, post decremento
Pre incremento, Pre decremento
Cambio de signo (-)
Complemento a nivel de bit
NOT booleano
Creacin de objetos
Cast (conversin de tipos)
Multplicacin, divisin, mdulo. Vlido tb
para fp
Suma, resta
Concatenacin de cadenas
Desplazamiento a izquierda
Desplazamiento a derecha con signo
Desplazamiento a derecha con ceros
Menor que, menor igual que
Mayor que, mayor igual que
Comparacin de tipo
Igual (tiene el mismo valor)
No igual ( diferente valor)
Igual (mismo objeto)
No igual ( diferente objeto)
And booleano a nivel de bits
And Booleano
XOR booleano a nivel de bits
XOR Booleano
OR booleano a nivel de bits
OR Booleano
AND Condicional
OR Condicional
Operador condicional (if)
Asignacin con operacin

P: Precedencia
A : Asociatividad (I=Izquierda, D=Derecha)

Elementos lxicos de Java

-4-

Fernando Berzal

Elemento
Asignacin
Llamada
Instanciacin
Secuencia
Vaca
Etiqueta
Variable
if
switch

while
do
for
break
continue
return
synchronized
throw
try

Objetivo
Evaluacin de una expresin
y almacenamiento del valor
obtenido como resultado
Llamada a un mtodo
Creacin de un objeto
Grupo de instrucciones
No hacer nada
Etiquetado
de una instruccin
Declaracin
de una variable
Condicional

Sintaxis
var = expr;
expr++;
method();
new Type( )
{ instrucciones }
;
etiqueta: instruccin

[final] tipo nombre [=valor]


[, nombre [=valor]];
if (expr) instruccin
[else instruccin]
Condicional
switch (expr) {
[case expr : instrucciones ]
[default : instrucciones]
}
Bucle
while (expr) instruccin
Bucle
do instruccin while (expr);
Bucle
for (init; test; increment) instruccin
Salir de un bloque
break [etiqueta] ;
Reiniciar un bucle
continue [etiqueta];
Resultado de un mtodo
return [expr];
Seccin crtica
synchronized (expr) {instrucciones}
Lanzamiento de excepciones throw expr;
Manejo de excepciones
try {instrucciones}
[catch (tipo) {instrucciones}]
[finally {instrucciones}]

Elementos lxicos de Java

-5-

Fernando Berzal

Introduccin a la programacin
Relacin de ejercicios
Conceptos bsicos
1. Escriba (en lenguaje natural) un algoritmo adecuado para la elaboracin de su
receta de cocina favorita. Analice las caractersticas de su algoritmo
(especialmente, su precisin).
2. Elabore, en lenguaje natural, dos algoritmos que permitan calcular el mximo
comn divisor de dos nmeros enteros positivos. Analice las caractersticas de
los algoritmos propuestos (precisin, finitud y eficiencia).
NOTA: Busque informacin sobre el algoritmo de Euclides.
Datos, tipos de datos y expresiones
3. Traduzca las siguientes frmulas a expresiones escritas en Java, declarando para
ello las variables que considere necesarias:
9
a. F = C + 32
5

1+

b.

f ( x, y ) =

c.

ex
1 + 2
x

x2
y

x3
1+ y

4. Cul es el resultado de evaluar las siguientes expresiones si suponemos que,


inicialmente, x vale 1?
a. (x > 1) & (x++ < 10)
b. (1 > x) && ( 1 > x++)
c. (1 == x) | (10 > x++)
d. (1 == x) || (10 > x++)
e. (++x) + x;
f. x + (++x)

Programas
5. Disee un programa que lea los coeficientes de una ecuacin de segundo grado
ax2+bx+c=0 y calcule sus dos soluciones. Se supone que la ecuacin tiene
soluciones reales.
6. Disee un programa que lea los coeficientes de un sistema de dos ecuaciones
lineales con dos incgnitas y calcule su solucin. Se supone que el sistema de
ecuaciones es compatible determinado.
ax + by = c

dx + ey = f
7. Implemente un programa que, dados los tres vrtices de un tringulo, calcule el
rea del mismo. Puede aplicar la siguiente frmula:
S = T (T S1 )(T S 2 )(T S 3 )
donde S1, S2 y S3 son las longitudes de los tres lados del tringulo y T es la mitad
de su permetro.
8. Dada una medida de tiempo expresada en horas, minutos y segundos con valores
arbitrarios, elabore un programa que transforme dicha medida en una expresin
correcta. Por ejemplo, dada la medida 3h 118m 195s, el programa deber
obtener como resultado 5h 1m 15s.
9. Escriba un programa en Java que nos calcule el cambio que debe dar la caja de
un supermercado: Dado un precio y una cantidad de dinero, el programa nos dir
cuntas monedas deben darse como cambio de tal forma que el nmero total de
monedas sea mnimo.
10. El precio final de un producto para un comprador es la suma total del costo del
producto, un porcentaje de beneficios que obtiene el vendedor y el I.V.A.
Disear un algoritmo para obtener el precio final de un producto sabiendo su
costo, el porcentaje de beneficios y el I.V.A. aplicable. Obtener el resultado
redondeando a los cinco cntimos (p.ej. 5.94 5.95).
11. Un banco recibe todos los das del Banco Mundial una lista de cmo est el
cambio de las divisas del mundo respecto del dlar americano (USD). Disear
un algoritmo que, a partir de una cantidad de dlares que deseamos comprar, nos
devuelva la cantidad en euros (y en pesetas) que nos costaran esos dlares.
Suponga que el banco obtiene en el cambio un tanto por ciento variable de
beneficios.
NOTA: 1 euro = 166.386 pesetas

Introduccin a la programacin
Relacin de ejercicios
Datos, tipos de datos y expresiones
1. Traduzca las siguientes frmulas a expresiones escritas en Java, declarando para
ello las variables que considere necesarias:
9
a. F = C + 32
5
int c, f;

Solucin
Error comn

f = 9*c/5 + 32;
f = 9/5*c + 32; // == 1*c + 32

float c, f;

Solucin
f = 9*c/5 + 32;
Error comn
f = (9/5)*c + 32; // == 1*c + 32
Solucin alternativa f = (9.0/5.0)*c + 32;

1+

b.

f ( x, y ) =

x2
y

x3
1+ y

double x,y;
double f;

// Tanto x como y
// han de ser != 0

f = ( 1 + x*x/y ) / ( x*x*x / (1+y) );


// ERROR: Tal como est escrita la expresin,
//
y debera tener un valor distinto de -1
f = ( 1 + x*x/y ) * (1+y) / ( x*x*x );

c.

ex
1 + 2
x

double x;
Math.sqrt ( 1 + Math.pow( Math.exp(x)/(x*x), 2) )
Math.sqrt ( 1 + Math.exp(2*x) / Math.pow(x,4) )
Math.sqrt ( 1 + Math.exp(2*x) / (x*x*x*x) )

2. Cul es el resultado de evaluar las siguientes expresiones si suponemos que,


inicialmente, x vale 1?
a. (x > 1) & (x++ < 10)
false
(1 > 1) & (1 < 10) == false & true == false
x = 2;

b. (1 > x) && ( 1 > x++)


false
(1 > 1) && (1 > 1) == (1 > 1) == false
x = 2;
c. (1 == x) | (10 > x++)
true
(1 == 1) | (10 > 1) == true | true == true
x = 2;
d. (1 == x) || (10 > x++)
true
(1 == 1) || (10 > 1) == true || true == true
x = 2;
e. (++x) + x;
4
x = 1
(++x) + x
x = 2;
x + x == 2 + 2 == 4
f. x + (++x)
3
x
1
x
1

=
+
=
+

1;
(++x)
2;
x == 1 + 2 == 3

Programacin orientada a objetos


En vez de un procesador de celdas de memoria
tenemos un universo de objetos de buen comportamiento
que cortsmente solicitan a las dems llevar a cabo sus deseos
-- Ingalls, 1981 (revista Byte)

Evolucin
Aos 60

Simula
Resolucin de problemas de simulacin
Ole-Johan Dahl & Krysten Nygaard (Noruega)

Aos 70

Smalltalk
Entorno de programacin entendible por novatos
Alan Kay (Xerox PARC, Palo Alto, California)

Aos 80

C++
Extensin de C
Bjarne Stroustroup (AT&T Bell Labs)

Aos 90

Java
Write once, run everywhere
Sun Microsystems

Conceptos bsicos
Todo es un objeto
Los objetos se comunican entre s pasndose mensajes
Cada objeto tiene un estado
(contiene su propia memoria [datos])
Un objeto es un caso particular (instancia) de una clase
Las clases definen el comportamiento de un conjunto de objetos

OOP Introduccin: Java

-1-

Fernando Berzal

Resolucin de problemas con orientacin a objetos


Problema
Quiero enviar un paquete a un amigo que vive en otra ciudad
Opciones

a) Hacerlo todo yo mismo


Descomposicin en subproblemas
(programacin estructurada)
b) Delegar en alguien para que lo haga (p.ej. Correos)
Realizar un encargo
(programacin orientada a objetos)
Solucin orientada a objetos

Se busca un objeto capaz de enviar un paquete


Se le enva un mensaje con mi solicitud
El objeto se hace responsable de satisfacer mi solicitud
El objeto utiliza un algoritmo que yo no tengo por qu conocer
Consecuencias

Un programa orientado a objetos se estructura como un conjunto


de agentes que interactan (programa como coleccin de objetos).
Cada objeto proporciona un servicio que es utilizado por otros
objetos (reutilizacin).
La accin se inicia por la transmisin de un mensaje al objeto
responsable de realizarla.
Si el receptor acepta el mensaje, acepta la responsabilidad de
llevar a cabo la accin solicitada.
El receptor puede utilizar cualquier tcnica que logre el objetivo
deseado.

OOP Introduccin: Java

-2-

Fernando Berzal

Clases y objetos
Clase
Implementacin de un tipo de dato.
Una clase sirve tanto de mdulo como de tipo
- Tipo:

Descripcin de un conjunto de objetos


(equipados con ciertas operaciones).

- Mdulo:

Unidad de descomposicin del software.

Objeto
Instancia de una clase:
Unidad atmica que encapsula estado y comportamiento.
Un objeto puede caracterizar una entidad fsica (un telfono, un
interruptor, un cliente) o una entidad abstracta (un nmero, una
fecha, una ecuacin matemtica).
Todos los objetos son instancias de una clase: Los objetos se crean
por instanciacin de las clases.
Todos los objetos de una misma clase (p.ej. coches) comparten
ciertas caractersticas: sus atributos (tamao, peso, color, potencia
del motor) y el comportamiento que exhiben (aceleran, frenan,
curvan).

OOP Introduccin: Java

-3-

Fernando Berzal

Todo objeto tiene


- Identidad (puede distinguirse de otros objetos)
- Estado (datos asociados a l)
- Comportamiento (puede hacer cosas)

Las diferentes instancias de cada clase difieren entre s por los valores
de los datos que encapsulan (sus atributos).
Dos objetos con los mismos valores en sus atributos pueden ser
diferentes.

TODOS los objetos de una misma clase usan el mismo algoritmo como
respuesta a mensajes similares.
El algoritmo empleado como respuesta a un mensaje (esto es, el mtodo
invocado) viene determinado por la clase del receptor.

Una clase es una descripcin de un conjunto de objetos similares.


Al programar, definimos una clase para especificar cmo se comportan
y mantienen su estado los objetos de esa clase.
A partir de la definicin de la clase, se crean tantos objetos de esa clase
como nos haga falta

OOP Introduccin: Java

-4-

Fernando Berzal

Clases en Java
Cada clase en Java:
Se define en un fichero independiente con extensin .java.
Se carga en memoria cuando se necesita.
La mquina virtual Java determina en cada momento las clases
necesarias para la aplicacin y las carga en memoria.
El programa puede ampliarse dinmicamente (sin tener que recompilar):
La aplicacin no es un bloque monoltico de cdigo.

Para definir una clase en Java se utiliza la palabra reservada class,


seguida del nombre de la clase (un identificador):

public class MiClase


{

NOTA: Es necesario que indiquemos el modificador de acceso public


para que podamos usar nuestra clase desde el exterior.

Los lmites de la clase se marcan con llaves { }


?

Se debe sangrar el texto que aparece entre las llaves para


que resulte ms fcil delimitar el mbito de los distintos
elementos de nuestro programa. De esta forma se mejora
la legibilidad de nuestro programa.

OOP Introduccin: Java

-5-

Fernando Berzal

Acerca del nombre de las clases


El nombre de una clase debe ser un identificador vlido en Java.
Por convencin, los identificadores que se les asignan a las clases en
Java comienzan con mayscula.
Adems, en Java, las clases pblicas deben estar definidas en ficheros
con extensin .java cuyo nombre coincida exactamente con el
identificador asignado a la clase (ojo con las maysculas y las
minsculas, que en Java se consideran diferentes!)

Errores comunes
Cuando el nombre de la clase no coincide con el nombre del
fichero, el compilador nos da el siguiente error:
Public class MiClase must be defined
in a file called MiClase.java

donde MiClase es el nombre de nuestra clase.


Las llaves siempre deben ir en parejas: Si falta la llave de cierre }
el compilador da un error:
} expected

Lo mismo ocurre si se nos olvida abrir la llave ({):


{ expected

Es una buena costumbre cerrar inmediatamente una


llave en cuanto se introduce en el texto del programa.
Despus se posiciona el cursor entre las dos llaves y se
completa el texto del programa.

OOP Introduccin: Java

-6-

Fernando Berzal

Uso del compilador javac


Al compilar un programa con javac,
el compilador nos muestra la lista de errores que se han detectado.
Para cada error, el compilador nos ofrece los siguientes datos:
- El nombre del fichero donde est el error.
- La lnea en la que se ha detectado el error.
- Un mensaje descriptivo del tipo de error (en ingls).
- Una reproduccin de la lnea donde se detect el error.
- La posicin exacta donde se detect el error en la lnea.
Ejemplos
Al compilar el fichero Error.java, cuyo contenido es
public class 2Error
{
}

el compilador nos da los siguientes errores:


Error.java:1: malformed floating point literal
public class 2Error
^
Error.java:4: '{' expected
^
2 errors

El primer error se produce porque el identificador de la clase no es


vlido y el segundo error es consecuencia del anterior.
Si cambiamos el identificador de la clase por un identificador vlido en
Java, se produce un error si el nombre de la clase con el nombre del
fichero:
Error.java:1: class Error3 is public,
should be declared in a file named Error3.java
public class Error3
^
1 error
OOP Introduccin: Java

-7-

Fernando Berzal

El compilador tambin nos dar un error si se nos olvida el punto y


coma del final de una sentencia o de una declaracin, tal como sucede
en el siguiente ejemplo:
public class Error
{
int x
}

En este caso, el error se detecta en la lnea siguiente a la declaracin de


la variable x:
Error.java:4: ';' expected
}
^
1 error

En la mayora de los lenguajes de programacin, Java incluido,


el compilador ignora los espacios y lneas en blanco
que introduzcamos en el texto del programa.
?

Los espacios y lneas en blanco los usaremos nosotros


para mejorar la legibilidad del texto del programa.

Cuando el compilador nos da un error, debemos comprobar la lnea en


la que se detecta el error para corregirlo. Si esa lnea no contiene errores
sintcticos, entonces debemos analizar las lneas que la preceden en el
texto del programa.

OOP Introduccin: Java

-8-

Fernando Berzal

Encapsulacin de datos (variables) y operaciones (mtodos)


Objeto = Identidad + Estado + Comportamiento

Identidad
La identidad de un objeto lo identifica unvocamente:
- Es independiente de su estado.
- No cambia durante la vida del objeto.
Estado
El estado de un objeto viene dado por los valores de sus atributos.
- Cada atributo toma un valor en un dominio concreto.
- El estado de un objeto evoluciona con el tiempo
- Los atributos de un objeto no deberan ser manipulables
directamente por el resto de objetos del sistema (ocultamiento de
informacin):
o Se protegen los datos de accesos indebidos.
o Se distingue entre interfaz e implementacin.
o Se facilita el mantenimiento del sistema.
Interfaz vs. implementacin
Los objetos se comunican a travs de interfaces bien
definidas sin tener que conocer los detalles internos de
implementacin de los dems objetos.
Ejemplo: Un coche se puede conducir
- Sin saber exactamente de qu partes consta el
motor ni cmo funciona ste (implementacin).
- Basta con saber manejar el volante,
el acelerador y el freno (interfaz).
OOP Introduccin: Java

-9-

Fernando Berzal

Comportamiento
Los mtodos que definen el comportamiento de un objeto:
- Agrupan las competencias del objeto (responsabilidades)
- Describen sus acciones y reacciones.
Las acciones realizadas por un objeto son consecuencia
directa de un estmulo externo (un mensaje enviado desde otro
objeto) y dependen del estado del objeto.

El interfaz de un objeto ha de establecer un contrato, un conjunto de


condiciones precisas que gobiernan las relaciones entre una clase
proveedora y sus clientes (diseo por contrato).

Estado y comportamiento estn relacionados.


Ejemplo
Un avin no puede aterrizar (accin) si no est en vuelo (estado)

Representacin grfica de una clase (notacin UML)


Una clase se representa con un rectngulo dividido en tres partes:
- El nombre de la clase
(identifica la clase de forma unvoca)
- Sus atributos
(datos asociados a los objetos de la clase)
- Sus operaciones
(comportamiento de los objetos de esa clase)
IMPORTANTE: Las clases se deben identificar con un nombre que, por
lo general, pertenecer al vocabulario utilizado habitualmente al
hablar del problema que tratamos de resolver.
OOP Introduccin: Java

- 10 -

Fernando Berzal

Representacin de una clase:


public class Cuenta
{

Declaracin en Java de una clase.


Representacin de una clase con sus atributos:

public class Cuenta


{
private double balance;
private double limit;

// Saldo
// Lmite

Las variables de instancia


sirven para especificar en Java los atributos de la clase.
Representacin del tipo y de los valores por defecto de los atributos:

public class Cuenta


{
private double balance = 0;
private double limit;

NOTA: Aqu hemos decidido utilizar el tipo primitivo


double para representar cantidades de dinero. En un
programa en el que no se pudiesen permitir errores
de redondeo en los clculos, deberamos utilizar otro
tipo ms adecuado (por ejemplo, BigDecimal).
OOP Introduccin: Java

- 11 -

Fernando Berzal

Representacin de las operaciones de una clase:

public class Cuenta


{
private double balance = 0;
private double limit;
public void ingresar ()
public void retirar ()
}

Los mtodos implementan en Java las operaciones


caractersticas de los objetos de una clase concreta.

Especificacin completa de la clase:

public class Cuenta


{
private double balance = 0;
private double limit;
public void ingresar (double cantidad)
{
balance = balance + cantidad;
}
public void retirar (double cantidad)
{
balance = balance cantidad;
}
}
OOP Introduccin: Java

- 12 -

Fernando Berzal

Clase de ejemplo
Representacin grfica en UML:

Definicin en Java:
Fichero Motocicleta.java

public class Motocicleta


{
// Atributos (variables de instancia)
private String matricula;

// Placa de matrcula

private String color;

// Color de la pintura

private int velocidad;

// Velocidad actual (km/h)

private boolean en_marcha; // moto arrancada?


// Operaciones (mtodos)
public void arrancar ()
{ }
public void acelerar ()
{ }
public void frenar ()
{ }
public void girar (float angulo)
{ }
}

OOP Introduccin: Java

- 13 -

Fernando Berzal

Uso de objetos
El operador .
El operador . (punto) en Java
nos permite acceder a los distintos miembros de una clase:
objeto.miembro

Cuando tenemos un objeto de un tipo determinado y queremos acceder


a uno de sus miembros slo tenemos que poner el identificador asociado
al objeto (esto es, el identificador de una de las variables de nuestro
programa) seguido por un punto y por el identificador que hace
referencia a un miembro concreto de la clase a la que pertenece el
objeto.
Cmo se comprueba el estado de un objeto?
Accediendo a las variables de instancia del objeto
objeto.atributo

Por ejemplo, cuenta.balance nos permitira acceder


al valor numrico correspondiente al saldo de una cuenta,
siempre y cuando cuenta fuese una instancia de la clase Cuenta.
Cmo se le enva un mensaje a un objeto?
Invocando a uno de sus mtodos.
objeto.mtodo(lista de parmetros)

La llamada al mtodo hace que el objeto realice la tarea


especificada en la implementacin del mtodo, tal como est
definida en la definicin de la clase a la que pertenece el objeto.
OOP Introduccin: Java

- 14 -

Fernando Berzal

Ejemplos

cuenta.ingresar(150.00);

- Si cuenta es el identificador asociado a una variable de tipo


Cuenta, se invoca al mtodo ingresar definido en la clase
Cuenta para depositar una cantidad de dinero en la cuenta.
- La implementacin del mtodo ingresar se encarga de actualizar
el saldo de la cuenta, sin que nosotros nos tengamos que
preocupar de cmo se realiza esta operacin.

System.out.println(Mensaje);

- System es el nombre de una clase incluida en la biblioteca de


clases estndar de Java.
- System.out es un miembro de la clase System que hace
referencia al objeto que representa la salida estndar de una
aplicacin Java.
- println() es un mtodo definido en la clase a la que pertenece el
objeto System.out.
- La implementacin del mtodo println() se encarga de mostrar
el mensaje que le pasamos como parmetro y hace avanzar el
cursor hasta la siguiente lnea (como si pulssemos la tecla ).
- System.out.println() es una llamada a un mtodo, el mtodo
println() del objeto System.out
- La lnea completa forma una sentencia (terminada con un punto y
coma) que delega en el mtodo println() para que ste se
encargue de mostrar una lnea en pantalla.

OOP Introduccin: Java

- 15 -

Fernando Berzal

Creacin de objetos
Antes de poder usar un objeto hemos de crearlo
El operador new
El operador new nos permite crear objetos en Java.
Tipo identificador = new Tipo();

Si escribimos un programa como el siguiente:


public class Ingreso
{
public static void main (String args[])
{
Cuenta cuenta;
// Error
cuenta.ingresar(100.00);
}
}

El compilador nos da el siguiente error:


Ingreso.java:7:
variable cuenta might not have been initialized
cuenta.ingresar(100.00);
^

Hemos declarado una variable que, inicialmente, no tiene ningn valor.


Antes de utilizarla, deberamos haberla inicializado (con un objeto del
tipo adecuado):
Cuenta cuenta = new Cuenta();

Observaciones
- Se suele crear una clase aparte, que nicamente contenga un
mtodo main, como punto de entrada de la aplicacin.
- En la implementacin del mtodo main se crean los objetos que
sean necesarios y se les envan mensajes para indicarles lo que
deseamos que hagan.
OOP Introduccin: Java

- 16 -

Fernando Berzal

Constructores
Cuando utilizamos el operador new acompaado del nombre de una
clase, se crea un objeto del tipo especificado (una instancia de la clase
cuyo nombre aparece al lado de new).
Al crear un objeto de una clase concreta, se invoca a un mtodo especial
de esa clase, denominado constructor, que es el que se encarga de
inicializar el estado del objeto.

Constructor por defecto


Por defecto, Java crea automticamente un constructor sin parmetros
para cualquier clase que definamos.

public class Cuenta


{
// Constante
public static final double LIMITE_NORMAL = 300.00;
// Variables de instancia
private double balance = 0;
private double limit = LIMITE_NORMAL;
// Mtodos
...
}

Al crear un objeto de tipo Cuenta con new Cuenta(), se llama al


constructor por defecto de la clase Cuenta, con lo cual se crea un
objeto de tipo Cuenta cuyo estado inicial ser el indicado en la
inicializacin de las variables de instancia balance y limit.

OOP Introduccin: Java

- 17 -

Fernando Berzal

Constructores definidos por el usuario


Los lenguajes de programacin nos permiten definir constructores para
especificar cmo ha de inicializarse un objeto al crearlo.

El nombre del constructor ha de coincidir con el nombre de la clase.

Podemos definir un constructor


para inicializar las variables de instancia de una clase,
en vez de hacerlo en la propia declaracin de las variables de instancia:
public class Cuenta
{
// Constante
public static final double LIMITE_NORMAL = 300.00;
// Variables de instancia
private double balance;
private double limit;
// Constructor sin parmetros
public Cuenta ()
{
this.balance = 0;
this.limit
= LIMITE_NORMAL;
}
// Mtodos
...
}

La palabra reservada this hace referencia al objeto


que realiza la operacin cuya implementacin especifica el mtodo.

OOP Introduccin: Java

- 18 -

Fernando Berzal

Tambin podemos definir constructores con parmetros:


public class Cuenta
{
// Constante
public static final double LIMITE_NORMAL = 300.00;
// Variables de instancia
private double balance;
private double limit;
// Constructor con parmetros
public Cuenta (double limit)
{
this.balance = 0;
this.limit = limit;
}
// Mtodos
...
}

Ahora, para crear un objeto de tipo Cuenta, hemos de especificar los


parmetros adecuados para su constructor:
Cuenta cuenta = new Cuenta(Cuenta.LIMITE_NORMAL);

O bien
Cuenta cuentaVIP = new Cuenta(6000.00);


  
 

La cuenta VIP tendr un lmite de 6000

En cuanto definimos un constructor, ya no podemos utilizar el


constructor por defecto de la clase (el constructor sin parmetros que
Java crea automticamente si no especificamos ninguno).

OOP Introduccin: Java

- 19 -

Fernando Berzal

Si slo est definido el constructor anterior


public Cuenta (double limit)

al crear un objeto con


Cuenta cuenta = new Cuenta();

el compilador de Java nos da el siguiente error:


CuentaTest.java:5: cannot find symbol
symbol : constructor Cuenta()
location: class Cuenta
Cuenta cuenta = new Cuenta();
^
1 error

porque no existe ningn constructor


sin parmetros definido para la clase Cuenta.

Para facilitarnos la creacin de objetos,


Java nos permite definir varios constructores para una misma clase
(siempre y cuando tengan parmetros diferentes).

De forma que podemos incluir los dos constructores


en la implementacin de la clase Cuenta y escribir lo siguiente:
public class CuentaTest
{
public static void main (String args[])
{
Cuenta cuentaNormal = new Cuenta();
Cuenta cuentaVIP
= new Cuenta(6000.00);

}
}
OOP Introduccin: Java

- 20 -

Fernando Berzal

Referencias
Cualquier tipo que definamos en Java con una clase
es un tipo no primitivo.
Cuando declaramos una variable de un tipo primitivo en Java, estamos
reservando espacio en memoria para almacenar
un valor del tipo correspondiente.
Sin embargo,
cuando declaramos una variable de un tipo no primitivo en Java,
lo nico que hacemos es reservar una zona en memoria
donde se almacenar una referencia a un objeto del tipo especificado
(y no el objeto en s, de ah la necesidad de utilizar el operador new).

Inicializacin por defecto de los objetos en Java


Cuando se crea un objeto con el operador new, por defecto:
- Las variables de instancia de tipo numrico (byte, short,
int, long, float y double) se inicializan a 0.
- Las variables de instancia de tipo char se inicializan a \0.
- Las variables de instancia de tipo boolean se inicializan a false.
- Las variables de instancia de cualquier tipo no primitivo se
inicializan a null (una palabra reservada del lenguaje que indica
que la referencia no apunta a ninguna parte).

IMPORTANTE
Para acceder a un miembro de un objeto
(leer el valor de una variable de instancia o invocar un mtodo)
hemos de tener una referencia a un objeto distinta de null

OOP Introduccin: Java

- 21 -

Fernando Berzal

Uso de sentencias de asignacin


Cuando usamos datos de tipos primitivos,
las sentencias de asignacin copian valores:
// Intercambio de los valores de dos variables
int x = 100;
int y = 200;
int tmp;
tmp = y;

// La variable temporal
// almacena el valor inicial de y

y = x;

// Se almacena en y el valor de x (100)

x = tmp;

// Se almacena en x
// el valor original de y (200)

Cuando usamos objetos (datos de tipos no primitivos),


las sentencias de asignacin copian referencias:
Cuenta miCuenta = new Cuenta();
Cuenta tmp;
tmp = miCuenta;

// Copia la referencia

tmp.ingresar(150);

// Se hace un ingreso en
//
miCuenta !!!

MUY IMPORTANTE
En una sentencia de asignacin,
no se crea una copia del dato representado por un objeto
(salvo que trabajemos con tipos primitivos)
OOP Introduccin: Java

- 22 -

Fernando Berzal

Relaciones entre clases:


Diagramas de clases UML
Las relaciones existentes entre las distintas clases
nos indican cmo se comunican los objetos de esas clases entre s:

Los mensajes navegan


por las relaciones existentes entre las distintas clases.

Existen distintos tipos de relaciones:


- Asociacin (conexin entre clases)
- Dependencia (relacin de uso)
- Generalizacin/especializacin (relaciones de herencia)

OOP Introduccin: Java

- 23 -

Fernando Berzal

Asociacin
Una asociacin es una relacin estructural
que describe una conexin entre objetos.

Grficamente, se muestra como una lnea continua


que une las clases relacionadas entre s.
Navegacin de las asociaciones
Aunque las asociaciones suelen ser bidireccionales (se pueden
recorrer en ambos sentidos), en ocasiones es deseable hacerlas
unidireccionales (restringir su navegacin en un nico sentido).
Grficamente, cuando la asociacin es unidireccional, la lnea
termina en una punta de flecha que indica el sentido de la
asociacin:

Asociacin unidireccional

Asociacin bidireccional
OOP Introduccin: Java

- 24 -

Fernando Berzal

equivale a

class Cuenta
{
private Dinero balance;
public void ingresar (Dinero cantidad)
{
balance += cantidad;
}
public void retirar (Dinero cantidad)
{
balance -= cantidad;
}
public Dinero getSaldo ()
{
return balance;
}
}

Hemos supuesto que Dinero es un tipo de dato con el que se pueden


hacer operaciones aritmticas y hemos aadido un mtodo adicional que
nos permite comprobar el saldo de una cuenta.
OOP Introduccin: Java

- 25 -

Fernando Berzal

viene a ser lo mismo que

con la salvedad de
que el enlace bidireccional hemos de mantenerlo nosotros

public class Cuenta


{

private Cliente titular;

}
public class Cliente
{

private Cuenta cuenta[];

Un cliente puede tener varias cuentas, por lo que en la clase cliente


hemos de mantener un conjunto de cuentas (un vector en este caso).
OOP Introduccin: Java

- 26 -

Fernando Berzal

Multiplicidad de las asociaciones


La multiplicidad de una asociacin determina
cuntos objetos de cada tipo intervienen en la relacin:

El nmero de instancias de una clase que se relacionan


con UNA instancia de la otra clase.

- Cada asociacin tiene dos multiplicidades


(una para cada extremo de la relacin).

- Para especificar la multiplicidad de una asociacin hay que indicar la


multiplicidad mnima y la multiplicidad mxima (mnima..mxima)

Multiplicidad
1
0..1
N..M
*
0..*
1..*

Significado
Uno y slo uno
Cero o uno
Desde N hasta M
Cero o varios
Cero o varios
Uno o varios (al menos uno)

- Cuando la multiplicidad mnima es 0, la relacin es opcional.

- Una multiplicidad mnima mayor o igual que 1 establece una


relacin obligatoria.

OOP Introduccin: Java

- 27 -

Fernando Berzal

dirige

Profesor

Departamento
0..1

Todo departamento tiene un director.


Un profesor puede dirigir un departamento.

Todo profesor pertenece a un departamento.


A un departamento pueden pertenecer varios profesores.

Relacin opcional
Un cliente puede o no
ser titular de una cuenta

Relacin obligatoria
Una cuenta ha de tener
un titular como mnimo

Relaciones involutivas
Cuando la misma clase aparece en los dos extremos de la asociacin.

OOP Introduccin: Java

- 28 -

Fernando Berzal

Agregacin y composicin
Casos particulares de asociaciones:
Relacin entre un todo y sus partes

Grficamente,
se muestran como asociaciones con un rombo en uno de los extremos.

Agregacin
Las partes pueden formar parte de distintos agregados.

Composicin
Agregacin disjunta y estricta:
Las partes slo existen asociadas al compuesto
(slo se accede a ellas a travs del compuesto)

OOP Introduccin: Java

- 29 -

Fernando Berzal

Dependencia
Relacin (ms dbil que una asociacin) que muestra la relacin entre
un cliente y el proveedor de un servicio usado por el cliente.
- Cliente es el objeto que solicita un servicio.
- Servidor es el objeto que provee el servicio solicitado.

Grficamente, la dependencia se muestra como una lnea discontinua


con una punta de flecha que apunta del cliente al proveedor.

Ejemplo
Resolucin de una ecuacin de segundo grado

b b 2 4ac
x=
2a
Para resolver una ecuacin de segundo grado hemos
de recurrir a la funcin sqrt de la clase Math
para calcular una raz cuadrada.
NOTA:
La clase Math es una clase degenerada que no tiene
estado. Es, simplemente, una coleccin de funciones
de clculo matemtico.
OOP Introduccin: Java

- 30 -

Fernando Berzal

Herencia (generalizacin y especializacin)


La relacin entre una superclase y sus subclases

Objetos de distintas clases pueden tener atributos similares y exhibir


comportamientos parecidos (p.ej. animales, mamferos).

public class Empleado


{
...
}
public class Profesor extends Empleado
{
...
}
public class PAS extends Empleado
{
...
}

OOP Introduccin: Java

- 31 -

Fernando Berzal

La nocin de clase est prxima a la de conjunto:


Generalizacin y especializacin
expresan relaciones de inclusin entre conjuntos.

Instancias:

coches vehculos

- Todo coche es un vehculo.


- Algunos vehculos son coches.

Propiedades:

propiedades(coches) propiedades(vehculos)

- Un coche tiene todas las propiedades de un vehculo.


- Algunas propiedades del coche no las tienen todos los vehculos.

OOP Introduccin: Java

- 32 -

Fernando Berzal

Jerarquas de clases

Las clases se organizan


en una estructura jerrquica formando una taxonoma.

- El comportamiento de una categora ms general


es aplicable a una categora particular.

- Las subclases heredan caractersticas de las clases de las que se


derivan y aaden caractersticas especficas que las diferencian.

En el diagrama de clases,
los atributos, mtodos y relaciones de una clase se muestran en el nivel
ms alto de la jerarqua en el que son aplicables.

OOP Introduccin: Java

- 33 -

Fernando Berzal

Visibilidad
de los miembros de una clase
Se pueden establecer distintos niveles de encapsulacin
para los miembros de una clase (atributos y operaciones)
en funcin de desde dnde queremos que se pueda acceder a ellos:

Visibilidad
Pblica

Protegida

Privada

Significado
Se puede acceder al
miembro de la clase
desde cualquier lugar.
Slo se puede acceder
al miembro de la clase
desde la propia clase o
desde una clase que
herede de ella.
Slo se puede acceder
al miembro de la clase
desde la propia clase.

Java

UML

public

protected

private

Para encapsular por completo el estado de un objeto,


todos sus atributos se declaran como variables de instancia privadas
(usando el modificador de acceso private).

A un objeto siempre se accede a travs de sus mtodos pblicos


(su interfaz).
Para usar el objeto no es necesario conocer
qu algoritmos utilizan sus mtodos
ni qu tipos de datos se emplean para mantener su estado
(su implementacin).
OOP Introduccin: Java

- 34 -

Fernando Berzal

Diseo incorrecto

public class Persona


{
public String nombre;
public Persona padre;
public Persona madre;
public ArrayList hijos = new ArrayList();
}

Uso correcto de la clase:


Persona juan = new Persona();
Persona carlos = new Persona();
Persona silvia = new Persona();
juan.nombre = Juan;
carlos.nombre = Carlos;
silvia.nombre = Silvia;
juan.padre = carlos;
juan.madre = silvia;
carlos.hijos.add(juan);
silvia.hijos.add(juan);

Uso incorrecto de la clase


(pese a ser vlido tal como est implementada):
juan.padre = carlos;
juan.madre = carlos;
silvia.hijos.add(juan);
juan.hijos.add(juan);

OOP Introduccin: Java

- 35 -

Fernando Berzal

Diseo correcto

import java.util.ArrayList;
public class Persona
{
// Variables de instancia privadas
private String nombre;
private Persona padre;
private Persona madre;
private ArrayList hijos = new ArrayList();
// Constructores pblicos
public Persona (String nombre)
{
this.nombre = nombre;
}
public Persona
(String nombre, Persona padre, Persona madre)
{
this.nombre = nombre;
this.padre = padre;
this.madre = madre;
padre.addHijo(this);
madre.addHijo(this);
}
OOP Introduccin: Java

- 36 -

Fernando Berzal

// Mtodo privado
private void addHijo (Persona hijo)
{
hijos.add(hijo);
}
// Mtodos pblicos
// p.ej. Acceso a las variables de instancia
public void setNombre (String nombre)
{
this.nombre = nombre;
}
public String getNombre ()
{
return nombre;
}

Con esta implementacin, desde el exterior de la clase


no se pueden modificar las relaciones existentes entre padres e hijos,
por lo que estas siempre se mantendrn correctamente
si implementamos bien la clase Persona.
Ejemplo
Persona carlos = new Persona(Carlos);
Persona silvia = new Persona(Silvia);
Persona juan = new Persona(Juan,carlos,silvia);

Operacin permitida (a travs de un mtodo pblico):


juan.setNombre(Antonio);

// Cambio de nombre

Operacin no permitida (error de compilacin):


addHijo(Persona) has private access in Persona
juan.addHijo(carlos);
^
OOP Introduccin: Java

- 37 -

Fernando Berzal

UML

El Lenguaje Unificado de Modelado


Grady Booch, Jim Rumbaugh e Ivar Jacobson

El lenguaje UML es un estndar OMG diseado para visualizar,


especificar, construir y documentar software orientado a objetos.

Un modelo es una simplificacin de la realidad.

El modelado es esencial en la construccin de software para


- Comunicar la estructura de un sistema complejo
- Especificar el comportamiento deseado del sistema
- Comprender mejor lo que estamos construyendo
- Descubrir oportunidades de simplificacin y reutilizacin

OOP Introduccin: Java

- 38 -

Fernando Berzal

Un modelo proporciona los planos de un sistema y puede ser ms o


menos detallado, en funcin de los elementos que sean relevantes en
cada momento.

El modelo ha de capturar lo esencial.

Todo sistema puede describirse desde distintos puntos de vista:


- Modelos estructurales (organizacin del sistema)
- Modelos de comportamiento (dinmica del sistema)
UML estandariza 9 tipos de diagramas para representar grficamente un
sistema desde distintos puntos de vista.
Ventaja principal de UML
Unifica distintas notaciones previas.
Rumbaugh
Booch

Jacobson

Odell
Shlaer-Mellor

Meyer

UML
Harel

Gamma et. al.


Embly

Wirfs-Brock
Fusion

Inconvenientes de UML
- Falta de integracin con otras tcnicas
(p.ej. diseo de interfaces de usuario)
- UML es excesivamente complejo (y no est del todo libre de
ambigedades): el 80% de los problemas puede modelarse
usando alrededor del 20% de UML
OOP Introduccin: Java

- 39 -

Fernando Berzal

Diagramas de clases
Muestran un conjunto de clases y sus relaciones

Los diagramas de clases proporcionan


una perspectiva esttica del sistema
(representan su diseo estructural).
Notacin
Atributos
[visibilidad] nombre [multiplicidad] [: tipo [= valor_por_defecto]]
Operaciones
[visibilidad] nombre ([[in|out] parmetro : tipo [, ]])[:tipo_devuelto]
-

Los corchetes indican partes opcionales.


Visibilidad: privada (-), protegida (#) o pblica (+)
Multiplicidad entre corchetes (p.ej. [2], [0..2], [*], [3..*])
Parmetros de entrada (in) o de salida (out).

OOP Introduccin: Java

- 40 -

Fernando Berzal

Diagramas de objetos
Muestran un conjunto de objetos y sus relaciones
(una situacin concreta en un momento determinado).

Los diagramas de objetos representan instantneas de instancias


de los elementos que aparecen en los diagramas de clases

Un diagrama de objetos expresa la parte esttica de una interaccin.

Para ver los aspectos dinmicos de la interaccin


se utilizan los diagramas de interaccin
(diagramas de secuencia y diagramas de comunicacin/colaboracin)

NOTA:
Los identificadores subrayados indican que se trata de objetos.
OOP Introduccin: Java

- 41 -

Fernando Berzal

Diagramas de interaccin
Muestran una interaccin concreta: un conjunto de objetos y sus
relaciones, junto con los mensajes que se envan entre ellos.
Diagramas de secuencia
Resaltan la ordenacin temporal de los mensajes que se intercambian.

: WInP rstamos

: Encargado

:Socio

:Video

: Prstamo

prestar(video, socio)
verificar situacin socio
verificar situacin video

registrar prstamo
entregar recibo

Diagramas de comunicacin (UML 2.0)


= Diagramas de colaboracin (UML 1.x)
Resaltan la organizacin estructural
de los objetosque intercambian mensajes.
:Socio

:Video
2: verificar situacin socio

1: prestar(video, socio)

3: verificar situacin video


:WInPrstamos

5: entregar recibo
: Encargado

4: registrar prstamo

:Prstamo

OOP Introduccin: Java

- 42 -

Fernando Berzal

Los diagramas de secuencia y de comunicacin son isomorfos:


- Un diagrama de secuencia se puede transformar mecnicamente
en un diagrama de comunicacin.
- Un diagrama de comunicacin se puede transformar
automticamente en un diagrama de secuencia.

Diagramas de secuencia
Muestran la secuencia de mensajes entre objetos durante un escenario
concreto (paso de mensajes).
- En la parte superior aparecen los objetos que intervienen.
- La dimensin temporal se indica verticalmente
(el tiempo transcurre hacia abajo).
- Las lneas verticales indican el perodo de vida de cada objeto.
- El paso de mensajes se indica con flechas horizontales u oblicuas
(cando existe demora entre el envo y la atencin del mensaje).
- La realizacin de una accin se indica con rectngulos sobre las
lneas de actividad del objeto que realiza la accin.

Diagramas de comunicacin/colaboracin
La distribucin de los objetos en el diagrama permite observar
adecuadamente la interaccin de un objeto con respecto de los dems
- La perspectiva esttica del sistema viene dada por las relaciones
existentes entre los objetos (igual que en un diagrama de objetos).
- La vista dinmica de la interaccin viene indicada por el envo de
mensajes a travs de los enlaces existentes entre los objetos.
NOTA:

OOP Introduccin: Java

Los mensajes se numeran para ilustrar


el orden en que se emiten.
- 43 -

Fernando Berzal

Otros diagramas UML


para representar aspectos dinmicos del sistema
- Diagramas de casos de uso
(actores y casos de uso del sistema)

C aso de U so

Actor

Los diagramas de uso se suelen utilizar en el modelado


del sistema desde el punto de vista de sus usuarios para
representar las acciones que realiza cada tipo de usuario.

- Diagramas de estados
(estados y transiciones entre estados),
contratar
en el paro

en ac tivo
perder em pleo
jubilarse
jubil arse

jub ilado

Los diagramas de estados son especialmente importantes


para describir el comportamiento de un sistema reactivo
(cuyo comportamiento est dirigido por eventos).
OOP Introduccin: Java

- 44 -

Fernando Berzal

- Diagramas de actividades
(flujo de control en el sistema)

Customer

Sales

Stockroom

Request
service

Take order
Play

Fill order

Deliver order

Collect
order

Los diagramas de actividades muestran el orden


en el que se van realizando tareas dentro de un sistema
(el flujo de control de las actividades).

OOP Introduccin: Java

- 45 -

Fernando Berzal

Diagramas UML
para representar aspectos fsicos del sistema
- Diagramas de componentes
(componentes y dependencias entre ellos)
Organizacin lgica de la implementacin de un sistema

- Diagramas de despliegue
(nodos de procesamiento y componentes)
Configuracin del sistema en tiempo de ejecucin
<<Cliente>>
Terminal Punto
de Venta

<<Servidor>>
<<TCP/IP>>

Base de
Datos

<<RDSI>>
<<LAN>>

OOP Introduccin: Java

- 46 -

Fernando Berzal

Referencias
Pginas web
http://www.uml.org/
Pgina oficial de UML, uno de los estndares promovidos por el OMG.
http://www.cetus-links.org/oo_uml.html
Coleccin de enlaces relacionados con UML.
http://www.agilemodeling.com/essays/umlDiagrams.htm
Informacin prctica acerca de todos los diagramas UML 2
http://www.ootips.org/
Ideas clave en programacin orientada a objetos.
Libros
Martin Fowler: UML Distilled:
A Brief Guide to the Standard Object Modeling Language
3rd edition. Addison-Wesley, 2004. ISBN 0321193687
Grady Booch et al.:
Object-Oriented Analysis and Design with Applications
3rd edition. Addison-Wesley, 2004. ISBN 020189551X
Craig Larman: Applying UML and Patterns: An Introduction to
Object-Oriented Analysis and Design and the Unified Process
2nd edition. Prentice-Hall, 2001. ISBN 0130925691
Robert C. Martin:
Agile Software Development: Principles, Patterns, and Practices
Prentice-Hall, 2003. ISBN 0135974445

OOP Introduccin: Java

- 47 -

Fernando Berzal

Programacin orientada a objetos


Relacin de ejercicios
1. Proponga tres ejemplos de objetos del mundo real:

Para cada uno de ellos, determine la clase a la que pertenecen.

Asciele a cada clase un identificador descriptivo adecuado.

Enumere varios atributos y operaciones para cada una de las clases.

Represente grficamente las clases utilizando la notacin UML.

A partir de los diagramas UML, escriba el cdigo necesario para definir


las clases utilizando el lenguaje de programacin Java.

2. Rellene los huecos en las siguientes afirmaciones:


a. Los objetos encapsulan ________ y _________.
b. Los objetos se comunican entre s pasndose _______.
c. Para comunicarse con un objeto concreto, no es necesario conocer su
_______, basta con saber cul es su ________.
d. Pueden existir varios tipos de relaciones entre clases: _______,
_______ y _______.
e. Los lenguajes de programacin orientada a objetos utilizan relaciones de
_______ para derivar nuevas clases a partir de clases base.
f. _____ define una notacin grfica estndar para representar diseos
orientados a objetos.
g. Las clases se definen en Java en ficheros de texto con la extensin _____
h. El compilador de Java genera ficheros con extensin ______ al compilar
un fichero de cdigo fuente escrito en Java.

3. Definir adecuadamente las clases en Java que se derivan de los siguientes


diagramas de clases UML:

Alumno
DNI
Nombre
Direccin
Beca
se matricula en
*
1..* Calificacin

Asignatura
ID
Grupo
impartida en
Nombre
ID
Crditos
1
1..* Tipo
Carcter
Curso
*
asignada a
Da
Hora
*
Aula

ID
Capacidad

ensea
*

1..*

Profesor
NRP
Nombre
Categora
rea
*
pertenece a

1
dirige

1
Departamento
ID
Nombre

Nota: CLASES ASOCIACIN


Las clases asociacin (como se matricula en) se emplean para indicar que la
asociacin existente entre dos clases tiene atributos propios:

En realidad, las clases asociacin de un diagrama de clases UML son clases


convencionales cuyo nico papel consiste en relacionar objetos de otras clases (no
tienen comportamiento propio)

Ejemplo

La fecha del alquiler no es un atributo del cliente ni de la pelcula,


es algo especfico del hecho de alquilar la pelcula.
class Cliente

class Pelicula

class Alquiler
{
private Cliente cliente;
private Pelicula peli;
private DateTime fecha;
public Alquiler
(Cliente cliente, Pelicula peli, DateTime fecha)
{
this.cliente = cliente;
this.peli = peli;
this.fecha = fecha;
}

Modularizacin
Uso de subprogramas
Razones vlidas para crear un subprograma
Pasos para escribir un subprograma
Acerca del nombre de un subprograma
Mtodos
Definicin de los mtodos: cabecera, cuerpo y signatura
Uso de los mtodos
Paso de parmetros
Devolucin de resultados (sentencia return)
Constructores (la palabra reservada this)
Mtodos estticos
mbito de las variables
Cohesin y acoplamiento

Bibliografa
Steve McConnell: Code Complete.
Microsoft Press, 2004 [2 edicin] ISBN 0735619670.
Microsoft Press, 1994 [1 edicin] ISBN 1556154844.

Uso de subprogramas
Los lenguajes de programacin permiten descomponer un programa
complejo en distintos subprogramas:
Funciones y procedimientos
en lenguajes de programacin estructurada
Mtodos
en lenguajes de programacin orientada a objetos

Razones vlidas para crear un subprograma


Reducir la complejidad del programa (divide y vencers).
Eliminar cdigo duplicado.
Mejorar la legibilidad del cdigo.
Limitar los efectos de los cambios (aislar aspectos concretos).
Ocultar detalles de implementacin
(ocultacin de informacin)
p.ej. algoritmos complejos
Promover la reutilizacin de cdigo
p.ej. componentes reutilizables y familias de productos
Facilitar la adaptacin del cdigo a nuevas necesidades
p.ej. interfaces de usuario
Mejorar la portabilidad del cdigo.
Modularizacin

-1-

Fernando Berzal

Pasos para escribir un subprograma


1. Definir el problema que el subprograma ha de resolver.
2. Darle un nombre no ambiguo al subprograma.
3. Decidir cmo se puede probar el funcionamiento del
subprograma (de esta forma, desde el comienzo se piensa en
cmo se utilizar el subprograma, lo que tiende a mejorar el
diseo de un interfaz adecuado para el subprograma).
4. Escribir la declaracin del subprograma:
- La cabecera de la funcin en lenguajes estructurados.
- La cabecera del mtodo en lenguajes orientados a objetos.
5. Buscar el algoritmo ms adecuado
para resolver el problema.
6. Escribir los pasos principales del algoritmo
como comentarios en el texto del programa.
7. Rellenar el cdigo correspondiente a cada comentario.
8. Revisar mentalmente cada fragmento de cdigo.
9. Repetir los pasos anteriores
hasta quedar completamente satisfecho.

Modularizacin

-2-

Fernando Berzal

El nombre de un subprograma
Al crear un subprograma hemos de darle un nombre:
Cuando el subprograma no devuelve ningn valor
(procedimientos y mtodos void):
El nombre del subprograma suele estar formado por un verbo
seguido, opcionalmente, del nombre de un objeto.
Ejemplos:

ingresar
realizarTransferencia
abonarImpuestos

El subprograma se encargar de realizar una operacin


independiente con respecto al resto del programa.
Cuando el subprograma devuelve un valor
(funciones y mtodos):
El nombre del subprograma suele ser una descripcin del valor
devuelto por la funcin o el mtodo.
Ejemplos:

saldoActual
saldoMedio

El subprograma se usar habitualmente para obtener un valor que


emplearemos dentro de una expresin.
Observaciones
El nombre debe describir todo lo que hace el subprograma.
Se deben evitar nombres genricos que no dicen nada
(vg. calcular)
Se debe ser consistente en el uso de convenciones.
Modularizacin

-3-

Fernando Berzal

Mtodos
Los mtodos definen
el comportamiento de los objetos de una clase dada
(lo que podemos hacer con los objetos de esa clase)

Los mtodos exponen la interfaz de una clase.

Un mtodo define la secuencia de sentencias


que se ejecuta para llevar a cabo una operacin:

La implementacin de la clase se oculta del exterior.

Los mtodos
Nos dicen cmo hemos de usar los objetos de una clase.
Nos permiten cambiar la implementacin de una clase sin tener que
modificar su interfaz (esto es, sin tener que modificar el cdigo que
utiliza objetos de la clase cuya implementacin cambiamos)
Ejemplo:
Utilizar un algoritmo ms eficiente
para resolver un problema concreto
sin tener que tocar el cdigo del resto del programa.

Modularizacin

-4-

Fernando Berzal

Definicin de mtodos
Sintaxis en Java

modificadores tipo nombre (parmetros)


{

cuerpo
}

La estructura de un mtodo se divide en:


Cabecera (determina su interfaz)
modificadores tipo nombre (parmetros)
Cuerpo (define su implementacin)
{
// Declaraciones de variables
...
// Sentencias ejecutables
...
// Devolucin de un valor (opcional)
...
}

En el cuerpo del mtodo se implementa el algoritmo necesario para


realizar la tarea de la que el mtodo es responsable.
El cuerpo de un mtodo se puede interpretar como una caja negra que
contiene su implementacin:
El mtodo oculta los detalles de implementacin.
Cuando utilizamos un mtodo, slo nos interesa su interfaz.
Modularizacin

-5-

Fernando Berzal

Ejemplo
El punto de entrada a una aplicacin escrita en Java

public static void main (String[] args)


{
...
}

Como todo en Java, ha de ser un miembro de una clase


(esto es, estar definido en el interior de una clase).
El modificador de acceso public indica que se puede acceder a
este miembro de la clase desde el exterior de la clase.
El modificador static indica que se trata de un mtodo de clase
(un mtodo comn para todos los objetos de la clase).
La palabra reservada void indica que, en este caso el mtodo main
no devuelve ningn valor.
En general, no obstante, los mtodos son capaces de devolver un
valor al terminar su ejecucin.
Los parntesis nos indican que se trata de un mtodo: Lo que
aparece entre parntesis son los parmetros del mtodo (en este
caso, un vector de cadenas de caracteres, que se representan en Java
con objetos de tipo String).
El cuerpo del mtodo va delimitado por llaves { }.

CONVENCIN
El texto correspondiente al cdigo que se ejecuta al invocar un mtodo
se sangra con respecto a la posicin de las llaves que delimitan el
cuerpo del mtodo.
Modularizacin

-6-

Fernando Berzal

La cabecera de un mtodo
La cabecera de un mtodo determina su interfaz
Modificadores de acceso (p.ej. public o private)
Determinan desde dnde se puede utilizar el mtodo.
Tipo devuelto (cualquier tipo primitivo, no primitivo o void)
Indica de que tipo es la salida del mtodo, el resultado que se
obtiene tras llamar al mtodo desde el exterior.
NOTA:
void se emplea cuando el mtodo no devuelve ningn valor.
Nombre del mtodo
Identificador vlido en Java
CONVENCIN:
En Java, los nombres de mtodos comienzan con minscula.
Parmetros formales
Entradas que necesita el mtodo para realizar la tarea de la que es
responsable.
MTODOS SIN PARMETROS:
Cuando un mtodo no tiene entradas, hay que poner ()

El cuerpo de un mtodo
El cuerpo de un mtodo define su implementacin:
NB: Como cualquier bloque de cdigo en Java,
el cuerpo de un mtodo ha de estar delimitado por llaves { }
Modularizacin

-7-

Fernando Berzal

La signatura de un mtodo
El nombre de un mtodo, los tipos de sus parmetros y el orden de los
mismos definen la signatura de un mtodo.
Los modificadores y el tipo del valor devuelto por un mtodo no
forman parte de la signatura del mtodo.

Sobrecarga
Lenguajes como Java permiten que existan distintos mtodos con el
mismo nombre siempre y cuando su signatura no sea idntica (algo
que se conoce con el nombre de sobrecarga)
Ejemplo
System.out.prinln();
- System.out.println()
- System.out.println(boolean)
- System.out.println(char)
- System.out.println(char[])
- System.out.println(double)
- System.out.println(float)
- System.out.println(int)
- System.out.println(long)
- System.out.println(Object)
- System.out.println(String)

No es vlido definir dos mtodos con el mismo nombre


que difieran nicamente por el tipo del valor que devuelven.
De todas formas, no conviene abusar demasiado de esta prestacin del
lenguaje, porque resulta propensa a errores
(en ocasiones, creeremos estar llamando a una versin
de un mtodo cuando la que se ejecuta en realidad es otra).
NOTA: En la creacin de constructores
s es importante disponer de esta caracterstica.
Modularizacin

-8-

Fernando Berzal

Uso de mtodos
Para enviarle un mensaje a un objeto,
invocamos (llamamos a) uno de sus mtodos:

La llamada a un mtodo de un objeto


le indica al objeto que delegamos en l
para que realice una operacin de la que es reponsable.

A partir de una referencia a un objeto,


podermos llamar a uno de sus mtodos con el operador .
Tras el nombre del mtodo, entre parntesis,
se han de indicar sus parmetros (si es que los tiene).
El mtodo podemos usarlo cuantas veces queramos.
MUY IMPORTANTE: De esta forma, evitamos la existencia de
cdigo duplicado en nuestros programas.

Ejemplo
Cuenta cuenta = new Cuenta();
cuenta.mostrarMovimientos();

Obviamente, el objeto debe existir antes de que podamos invocar uno


de sus mtodos. Si no fuese as, en la ejecucin del programa
obtendramos el siguiente error:
java.lang.NullPointerException
at ...

al no apuntar la referencia a ningn objeto (null en Java).


Modularizacin

-9-

Fernando Berzal

Ejemplo de ejecucin paso a paso


Cuando se invoca un mtodo, el ordenador pasa a ejecutar
las sentencias definidas en el cuerpo del mtodo:
public class Mensajes
{
public static void main (String[] args)
{
mostrarMensaje("Bienvenida");
// ...
mostrarMensaje("Despedida");
}
private static void mostrarMensaje (String mensaje)
{
System.out.println("*** " + mensaje + " ***");
}
}

Al ejecutar el programa (con java Mensajes):


1. Comienza la ejecucin de la aplicacin, con la primera sentencia
especificada en el cuerpo del mtodo main.
2. Desde main, se invoca mostrarMensaje con Bienvenida
como parmetro.
3. El mtodo mostrarMensaje muestra el mensaje de bienvenida
decorado y termina su ejecucin.
4. Se vuelve al punto donde estbamos en main y se contina la
ejecucin de este mtodo.
5. Justo antes de terminar, volvemos a llamar a mostrarMensaje
para mostrar un mensaje de despedida.
6. mostrarMensaje se vuelve a ejecutar, esta vez con
Despedida como parmetro, por lo que esta vez se muestra en
pantalla un mensaje decorado de despedida.
7. Se termina la ejecucin de mostrarMensaje y se vuelve al
mtodo desde donde se hizo la llamada (main).
8. Se termina la ejecucin del mtodo main y finaliza la ejecucin
de nuestra aplicacin.
Modularizacin

- 10 -

Fernando Berzal

Los parmetros de un subprograma


Un mtodo puede tener parmetros:
A travs de los parmetros se especifican los datos de entrada que
requiere el mtodo para realizar su tarea.
Los parmetros definidos en la cabecera del mtodo se denominan
parmetros formales.
Para cada parmetro, hemos de especificar tanto su tipo como un
identificador que nos permita acceder a su valor actual en la
implementacin del mtodo.
Cuando un mtodo tiene varios parmetros, los distintos parmetros
se separan por comas en la cabecera del mtodo.

En la definicin de un mtodo,
la lista de parmetros formales de un mtodo establece:
Cuntos parmetros tiene el mtodo
El tipo de los valores que se usarn como parmetros
El orden en el que han de especificarse los parmetros

En la invocacin de un mtodo,
se han de especificar los valores concretos para los parmetros.
Los valores que se utilizan como parmetros
al invocar un mtodo se denominan
parmetros actuales (o argumentos).
Modularizacin

- 11 -

Fernando Berzal

Cuando se efecta la llamada a un mtodo, los valores indicados como


parmetros actuales se asignan a sus parmetros formales.

En la implementacin del mtodo, podemos utilizar entonces los


parmetros del mtodo como si fuesen variables normales (y de esta
forma acceder a los valores concretos con los que se realiza cada
llamada al mtodo).
Obviamente, el nmero y tipo de los parmetros indicados en la
llamada al mtodo ha de coincidir con el nmero y tipo de los
parmetros especificados en la definicin del mtodo.

En Java, todos los parmetros se pasan por valor:

Al llamar a un mtodo,
el mtodo utiliza una copia local de los parmetros
(que contiene los valores con los cuales fue invocado).

OJO!

Como las variables de tipos no primitivos son, en realidad,


referencias a objetos, lo que se copia en este caso es la
referencia al objeto (no el objeto en s).
Como consecuencia, podemos modificar el estado de un
objeto recibido como parmetro si invocamos mtodos de
ese objeto que modifiquen su estado.
La referencia al objeto no cambia, pero s su estado.

Modularizacin

- 12 -

Fernando Berzal

Ejemplo: Intercambio incorrecto de valores


public void swap (int a, int b)
{
int aux;
aux = b;
a = b;
b = aux;
}
...
swap(a,b);

// Definicin

// Invocacin

Los valores de num1 y num2 se copian en a y b.


La ejecucin del mtodo swap no afecta ni a num1 ni a num2.
swap no intercambia los valores de las variables porque

el intercambio se hace sobre las copias locales de los parmetros de


las que dispone el mtodo, no sobre las variables originales.
Modularizacin

- 13 -

Fernando Berzal

Convenciones
Si varios mtodos utilizan los mismos parmetros,
stos han de ponerse siempre en el mismo orden.
De esta forma, resulta ms fcil de recordar
la forma correcta de usar un mtodo.
No es aconsejable utilizar los parmetros de una rutina como si
fuesen variables locales de la rutina.
En otras palabras, los parmetros no los utilizaremos para
almacenar resultados parciales.
Se han de documentar claramente las suposiciones que se hagan
acerca de los valores permitidos para los distintos parmetros de
un mtodo.
Esta informacin debera figurar en la documentacin del
cdigo realizada con la herramienta javadoc.
Slo se deben incluir los parmetros que realmente necesite el
mtodo para efectuar su labor.
Si un dato no es necesario para realizar un clculo, no tiene
sentido que tengamos que pasrselo al mtodo.
Las dependencias existentes entre distintos mtodos han de
hacerse explcitas mediante el uso de parmetros.
Si evitamos la existencia de variables globales (datos
compartidos entre distintos mdulos), el cdigo resultante
ser ms fcil de entender.

Modularizacin

- 14 -

Fernando Berzal

Devolucin de resultados: La sentencia

return

Cuando un mtodo devuelve un resultado, la implementacin


del mtodo debe terminar con una sentencia return:

return expresin;

Como es lgico, el tipo de la expresin debe coincidir con el tipo del


valor devuelto por el mtodo, tal como ste se haya definido en la
cabecera del mtodo.
Ejemplo
public static float media (float n1, float n2)
{
return (n1+n2)/2;
}
public static void main (String[] args)
{
float resultado = media (1,2);
System.out.println(Media = + resultado);
}

El compilador de Java comprueba que exista una sentencia return


al final de un mtodo que deba devolver un valor.
Si no es as, nos dar el error
Missing return statement

El compilador tambin detecta si hay algo despus de la sentencia


return (un error porque la sentencia return finaliza la ejecucin de
un mtodo y nunca se ejecuta lo que haya despus):
Unreachable statement

Modularizacin

- 15 -

Fernando Berzal

Ejemplo
Figuras geomtricas
//
//
//
//
//

Title:
Version:
Copyright:
Author:
E-mail:

Geometry
0.0
2004
Fernando Berzal
berzal@acm.org

public class Point


{
// Variables de instancia
private double x;
private double y;
// Constructor
public Point (double x, double y)
{
this.x = x;
this.y = y;
}
// Mtodos
public double distance (Point p)
{
double dx = this.x - p.x;
double dy = this.y - p.y;
return Math.sqrt(dx*dx+dy*dy);
}
public String toString ()
{
return "(" + x + "," + y + ")";
}
}

NB: La interfaz de la clase habra que documentarlo aadiendo


los correspondientes comentarios javadoc.
Modularizacin

- 16 -

Fernando Berzal

public class Circle


{
private Point centro;
private double radio;
// Constructor
public Circle (Point centro, double radio)
{
this.centro = centro;
this.radio = radio;
}
// Mtodos
public double area ()
{
return Math.PI*radio*radio;
}
public boolean isInside (Point p)
{
return ( centro.distance(p) < radio );
}
public String toString ()
{
return "Crculo con radio " + radio
+ " y centro en " + centro;
}
}

Ejemplo de uso
public static void main(String[] args)
{
Circle fig
= new Circle( new Point(0,0), 10);
Point dentro = new Point (3,3);
Point fuera = new Point (10,10);
System.out.println(figura);
System.out.println(dentro+"? "+fig.isInside(dentro));
System.out.println(fuera +"? "+fig.isInside(fuera) );
}
Modularizacin

- 17 -

Fernando Berzal

Constructores. La palabra reservada

this

Los constructores son mtodos especiales que sirven para inicializar el


estado de un objeto cuando lo creamos con el operador new
Su nombre ha de coincidir coincide con el nombre de la clase.
Por definicin, no devuelven nada.
public class Point
{
// Variables de instancia
private double x;
private double y;
// Constructor
public Point (double x, double y)
{
this.x = x;
this.y = y;
}
// Acceso a las coordenadas
public double getX ()
{
return x;
}
public double getY ()
{
return y;
}
}

NOTA:
La palabra reservada this permite acceder
al objeto sobre el que se ejecuta el mtodo.

Modularizacin

- 18 -

Fernando Berzal

La clave de implementar la clase Point de esta forma


(y no dar acceso directo a las variables de instancia)
es que podemos cambiar la implementacin de Point
para usar coordenadas polares
y la implementacin de las clases que trabajan con puntos
(p.ej. Circle) no hay que tocarla:

public class Point


{
// Variables de instancia
private double r;
private double theta;
// Constructor
public Point (double x, double y)
{
r
= Math.sqrt(x*x+y*y);
theta = Math.atan2(y,x);
}
// Acceso a las coordenadas
public double getX ()
{
return r*Math.cos(theta);
}
public double getY ()
{
return return r*Math.sin(theta);
}
}

Gracias a la encapsulacin,
podemos crear componentes reutilizables
cuya evolucin no afectar al resto del sistema.
Modularizacin

- 19 -

Fernando Berzal

Podemos definir varios constructores para poder inicializar un


objeto de distintas formas (siempre y cuando los constructores
tengan signaturas diferentes);
public class Contacto
{
private String nombre;
private String email;
public Contacto (String nombre)
{
this.nombre = nombre;
}
public Contacto (String nombre, String email)
{
this.nombre = nombre;
this.email = email;
}
}

Ejemplo de uso:
public class ContactoTest
{
public static void main(String[] args)
{
Contacto nico = new Contacto (Nicols);
Contacto juan = new Contacto (Juan,
juan@acm.org);
...
}
}

Constructor de copia
Un constructor que recibe como parmetro
un objeto de la misma clase que la del constructor

Modularizacin

- 20 -

Fernando Berzal

Otro ejemplo de uso de la palabra reservada this


consiste en llamar a un constructor desde otro de los constructores
(algo que, de hacerse, siempre ha de ponerse
al comienzo de la implementacin del constructor)

public class Contacto


{
private String nombre;
private String email;
public Contacto (String nombre)
{
this(nombre, );
}
public Contacto (String nombre, String email)
{
this.nombre = nombre;
this.email = email;
}
// Constructor de copia
public Contacto (Contacto otro)
{
this (otro.nombre, otro.email);
}
}

RECORDATORIO: Encapsulacin
Se consigue con los modificadores de acceso public y private.
Las variables de instancia de una clase suelen definirse como
privadas (con la palabra reservada private).
Los mtodos pblicos muestran la interfaz de la clase.
Pueden existir mtodos no pblicos que realicen tareas auxiliares
manteniendo la separacin entre interfaz e implementacin.
Modularizacin

- 21 -

Fernando Berzal

Mtodos estticos
Los mtodos estticos pertenecen a la clase
(no estn asociados a un objeto particular de la clase)
Ya hemos visto algunos ejemplos:
Math.pow(x,y)
public static void main (String[] args)

Para invocar un mtodo esttico,


usamos directamente el nombre de la clase (p.ej. Math)
No tenemos que instanciar antes un objeto de la clase.
main es un mtodo esttico

de forma que la mquina virtual Java


puede invocarlo sin tener que crear antes un objeto.

Como los mtodos estticos no estn asociados a objetos concretos,


no pueden acceder a las variables de instancia de un objeto
(las cuales pertenecen a objetos particulares).

Variables estticas = Variables de clase


Las clases tambin pueden tener variables que se suelen emplear para
representar constantes y variables globales a las cuales se pueda
acceder desde cualquier parte de la aplicacin (aunque esto ltimo no
es muy recomendable).
Ejemplos

System.out

Colores predefinidos:
Color.black, Color.red
Modularizacin

- 22 -

Fernando Berzal

Como es lgico,
los mtodos estticos slo pueden acceder a variables estticas.
public class Mensajes
{
private String mensaje = Hola;

// Error!

public static void main (String[] args)


{
mostrarMensaje(mensaje);
}
private static void mostrarMensaje (String mensaje)
{
System.out.println("*** " + mensaje + " ***");
}

}
El programa anterior funcionara correctamente
si hubisemos declarado mensaje como una variable esttica:
private static String mensaje = Hola;

NOTA: No es aconsejable declarar variables estticas


salvo para definir constantes, como sucede en la clase Math.

Mtodos estticos y variables estticas en la clase Math


Constantes matemticas: Math.PI, Math.E
Mtodos estticos: Funciones trigonomtricas (sin, cos,
tan, acos, asin, atan), logaritmos y exponenciales (exp,
log, pow, sqrt), funciones de redondeo (ceil, floor,
round [== Math.floor(x+0.5)], rint [al entero ms cercano,
se coge el par]), mximo y mnimo (max, min), valor absoluto
(abs), generacin de nmero pseudoaleatorios (random)
Modularizacin

- 23 -

Fernando Berzal

mbito de las variables


Una variable de instancia
es una variable definida para las instancias de una clase
(cada objeto tiene su propia copia de la variable de instancia).
Una variable esttica
es una variable definida para la clase
(compartida entre todas las instancias de una clase).
Una variable local
es una variable definida dentro del cuerpo de un mtodo.

El mbito de una variable es la parte del programa


en la que podemos hacer referencia a la variable
El mbito de una variable de instancia abarca todos los mtodos
no estticos de una clase:
o Cuando es privada, todos los mtodos pueden acceder al
valor almacenado en la variable de instancia.
o Cuando es pblica, se puede acceder a ella desde cualquier
lugar en el que se disponga de una referencia a un objeto de
la clase.
El mbito de una variable esttica:
o Si es privada, cubre todos los mtodos estticos de la clase
en que est definida.
o Si es pblica, abarca todos los mtodos estticos de todas
las clases que formen parte de la aplicacin.
El mbito de una variable local comienza en su declaracin y
termina donde termina el bloque de cdigo ({}) que contiene la
declaracin.
Modularizacin

- 24 -

Fernando Berzal

Uso de variables locales


En Java, las declaraciones se pueden poner en cualquier parte del
cdigo de un mtodo, no necesariamente al principio:

void method ()
{
int i=0;
while (i<10) {
int j=0;
...
}

// Declara e inicializa i
//
//
//
//

i est definido aqu


Declara j
i y j definidos
j ya no est definido

System.out.print(i); // i todava est definido


}
// i deja de estar definido

De todas formas, nosotros declararemos siempre todas las variables


locales al comienzo del cuerpo del mtodo.
Las variables locales han de declararse antes de utilizarse.
Se pueden declarar variables locales con el mismo nombre en
diferentes bloques de cdigo.
Incluso se podran declarar en bloques de cdigo no
anidados dentro de un mismo mtodo, aunque no es
recomendable hacerlo.

IMPORTANTE
Las variables de instancia se inicializan automticamente al crear un
objeto (a 0 o null), mientras que las variables locales de un mtodo
tenemos que inicializarlas nosotros antes de usarlas.
Modularizacin

- 25 -

Fernando Berzal

Cohesin y acoplamiento
Cohesin
Medida del grado de identificacin
de un mdulo con una funcin concreta.
Cohesin aceptable (fuerte)
COHESIN FUNCIONAL (un mdulo realiza una nica accin).
COHESIN SECUENCIAL (un mdulo contiene acciones que han
de realizarse en un orden particular sobre unos datos concretos).
COHESIN DE COMUNICACIN (un mdulo contiene un conjunto de
operaciones que se realizan sobre los mismos datos).
COHESIN TEMPORAL (las operaciones se incluyen en un mdulo
porque han de realizarse al mismo tiempo; p.ej. inicializacin).
Cohesin inaceptable (dbil)
COHESIN PROCEDURAL (un mdulo contiene operaciones que se
realizan en un orden concreto aunque sean independientes).
COHESIN LGICA (cuando un mdulo contiene operaciones cuya
ejecucin depende de un parmetro: el flujo de control del mdulo
es lo nico que une a las operaciones que lo forman).
COHESIN COINCIDENTAL (cuando las operaciones de un mdulo
no guardan ninguna relacin observable entre ellas).
Hay que procurar evitar situaciones de
cohesin procedural, lgica o coincidental
Modularizacin

- 26 -

Fernando Berzal

Acoplamiento
Medida de la interaccin
de los mdulos que constituyen un programa.
Niveles de acoplamiento (de mejor a peor):
ACOPLAMIENTO DE DATOS (acoplamiento normal): Todo lo que
comparten dos mdulos se especifica en la lista de parmetros del
mdulo invocado.
ACOPLAMIENTO DE CONTROL: Cuando un mdulo pasa datos que le
indican a otro qu hacer (el primer mdulo tiene que conocer
detalles internos del segundo).
ACOPLAMIENTO EXTERNO: Cuando dos mdulos utilizan los
mismos datos globales o dispositivos de E/S (p.ej. ficheros).
Si los datos son de slo lectura, el acoplamiento se puede
considerar aceptable. No obstante, en general, este tipo de
acoplamiento no es deseable porque la conexin existente
entre los mdulos no es visible (de forma explcita).
ACOPLAMIENTO PATOLGICO: Cuando un mdulo utiliza el cdigo
de otro o altera sus datos locales (acoplamiento de contenido).
Los lenguajes estructurados incluyen reglas para el mbito de
las variables que impiden este tipo de acoplamiento.
Los lenguajes orientados a objetos incluyen modificadores de
visibilidad para evitar este tipo de acoplamiento.

Objetivo final
Reducir al mximo el acoplamiento entre mdulos
y aumentar la cohesin interna de los mdulos.

Modularizacin

- 27 -

Fernando Berzal

Ejemplo
Clase Hipoteca
public class Hipoteca
{
double importe; // en euros
double interes; // en porcentaje (anual)
int
tiempo;
// en aos
// Constructor
public Hipoteca ()
// getters & setters
public double getImporte () {
return importe;
}
public void setCantidad (double euros) {
importe = euros;
}
public double getInteres () {
return interes;
}
public void setInteres (double tipoAnual) {
interes = tipoAnual;
}
public int getTiempo () {
return tiempo;
}
public void setTiempo (int years)
{
this.tiempo = years;
}
public double getCuota ()
{
double interesMensual = interes/(12*100);
double cuota = (cantidad*interesMensual)
/ (1.01.0/Math.pow(1+interesMensual,tiempo*12));
return Math.round(cuota*100)/100.0;
}
}
Modularizacin

- 28 -

Fernando Berzal

Convenciones get y set


Muchas clases suelen incluir mtodos pblicos que permiten acceder y
modificar las variables de instancia desde el exterior de la clase.
Por convencin, los mtodos se denominan:
getX para obtener la variable de instancia X, y
setX para establecer el valor de la variable de instancia X.

No es obligatorio, pero resulta conveniente, especialmente si


queremos desarrollar componentes reutilizables (denominados
JavaBeans) y facilitar su uso posterior.

import javax.swing.JOptionPane;
public class CuotaHipotecaria
{
public static void main (String args[])
{
double
cantidad; // en euros
double
interes; // en porcentaje (anual)
int
tiempo;
// en aos
Hipoteca hipoteca; // Hipoteca
// Entrada de datos
...
hipoteca = new Hipoteca(cantidad,interes,tiempo);
// Resultado
JOptionPane.showMessageDialog (null,

"Cuota mensual = "+hipoteca.getCuota()+"
System.exit(0);
}
}

Modularizacin

- 29 -

Fernando Berzal

Modularizacin
Relacin de ejercicios
1. Disee una clase Cuenta que represente una cuenta bancaria y permita realizar
operaciones como ingresar y retirar una cantidad de dinero, as como realizar
una transferencia de una cuenta a otra.
a. Represente grficamente la clase utilizando la notacin UML
b. Defina la clase utilizando la sintaxis de Java, definiendo las variables de
instancia y mtodos que crea necesarios.
c. Implemente cada uno de los mtodos de la clase. Los mtodos deben
actualizar el estado de las variables de instancia y mostrar un mensaje en
el que se indique que la operacin se ha realizado con xito.
d. Cree un programa en Java (en una clase llamada CuentaTest) que cree
un par de objetos de tipo Cuenta y realice operaciones con ellos. El
programa debe comprobar que todos los mtodos de la clase Cuenta
funcionan correctamente.

2. Disee una clase Factura que represente la venta de un producto en una tienda.
La clase debe incluir informacin relativa al producto vendido (cdigo,
descripcin y precio), datos acerca del cliente que compra el producto (nombre,
apellidos, direccin, DNI) y el nmero de unidades compradas. Los mtodos de
la clase han de permitir obtener el importe total de la compra (suponiendo un
porcentaje de IVA constante) y generar un informe con los datos de la factura (el
ticket correspondiente a la venta), adems de poder acceder y modificar los
distintos datos recogidos en la factura.
a. Represente grficamente en UML la clase resultante.
b. Implemente en Java la clase tal como est representada en el diagrama.
c. Cree un programa (FacturaTest) que compruebe el correcto
funcionamiento de la implementacin realizada.
d. Idee la forma de descomponer la clase Factura en varias clases de
forma que la implementacin resultante sea ms cohesiva y las clases
estn dbilmente acopladas. Represente su diseo en UML e
implemntelo en Java teniendo en cuenta las relaciones existentes entre
las distintas clases.
PISTA:
La factura mezcla varios datos de productos con datos relativos a clientes

3. CASO PRCTICO: Los precios de los telfonos mviles


Una empresa de telecomunicaciones nos ha encargado estudiar cul sera la
estrategia ms adecuada para fijar los precios de los nuevos telfonos mviles
UMTS:
a. En primer lugar, estudiamos cul ser la demanda de los nuevos
productos, para lo cual creamos un grfico como el siguiente:

La grfica muestra cmo la demanda vara en funcin del precio al que se


venda cada terminal. Cuanto ms alto sea el precio, menor ser el nmero
de personas dispuestas a pagarlo. Cuanto ms bajo sea el precio, mayor
ser el nmero de personas que lo compren, aunque la empresa ingresar
menos dinero por cada telfono mvil.
Para simplificar, suponemos que la curva de la demanda es una lnea
recta y creamos una clase Demanda que nos permitir representar la
demanda de un producto bajo diferentes circunstancias.
Dicha clase ha de incluir mtodos que nos digan cul ser la cantidad
demandada a un precio determinado y qu precio hemos de fijar para
conseguir vender una cantidad determinada de productos (esto es, a qu
precio podemos ofrecer el producto para asegurarnos una cantidad
demandada).
NOTA: Como siempre, una vez que tengamos la
clase, crearemos otra clase auxiliar que nos permita
comprobar su correcto funcionamiento.

b. A continuacin, pasamos a analizar el coste que supone para nosotros


producir telfonos mviles UMTS. El coste vendr dado por una
inversin fija (en la planta que hemos de construir para fabricar los
mviles) ms un coste marginal por unidad (que tender a cero cuantos
ms mviles fabriquemos. El coste total vendr dado por:
costetotal = costeinicial + unidades * costemarginal
Decidimos crear otra clase, Costes, para representar el coste de
produccin de un producto. Esta clase incluir un mtodo que nos dir
cunto nos cuesta fabricar un nmero determinado de unidades.

c. Finalmente, tenemos que calcular cules sern los ingresos que


obtendremos al vender telfonos mviles:
ingresos = precio * unidades
Decidimos crear otra clase, Ingresos, para representar el dinero que
obtendremos al vender telfonos mviles. Los ingresos, obviamente,
dependen de la demanda y del precio que decidamos establecer. La clase
deber ofrecer un mtodo que nos d los ingresos totales obtenidos a un
precio determinado.

d. Ahora se nos plantea el problema de ver cul es el precio ms ventajoso


para la empresa en funcin de la demanda y de los costes que ha de
afrontar. Este precio ideal lo podemos calcular de distintas formas:

A partir de los ingresos y gastos totales, buscamos cul es el


valor tal que la diferencia ingresos-costes es mxima.

Definimos el ingreso marginal como los ingresos adicionales


que nos supone vender una nueva unidad de nuestro producto
(bajando el precio de venta). Esto es, el ingreso marginal
vendr definido por la funcin:
ingresomarginal(x) = ingresototal(x) ingresototal(x-1)
En este caso, el precio ideal ser aquel para el que el ingreso
marginal obtenido por la venta de una unidad sea igual al coste
marginal de producir esa unidad. Si fuese mayor, podramos
vender ms unidades ganando ms dinero. Si fuese menor,
estaramos perdiendo beneficios al perder esa unidad.

Si la curva de la demanda es recta, el ingreso marginal puede


calcularse fcilmente si tenemos en cuenta la siguiente relacin:
ingresomarginal(x) = demanda(2x)
En este caso, el precio ideal seguir siendo aqul para el que el
ingreso marginal iguale al coste marginal, es decir aqul que
hace que costemarginal(x)=demanda(2x)

Implemente las distintas estrategias en Java y compruebe que todas


obtienen el mismo resultado si utilizamos los mismos datos de entrada.
NOTA: En vez de crear tres programas distintos, cree un nico
programa que acceda a una clase encargada de calcular el precio
ideal al que hay que vender el producto para una demanda
concreta. A continuacin, modifique la implementacin de la
clase sin alterar la implementacin del programa principal (desde
donde se leen los datos de entrada y se muestran los resultados).

e. Una vez que hemos creado la infraestructura necesaria para analizar el


comportamiento del mercado, podemos estudiar lo que sucede cuando
modificamos nuestra poltica de precios.

Todo al mismo precio: Si vendemos nuestro producto siempre


al mismo precio, los ingresos que obtendremos sern,
simplemente, el resultado de multiplicar precio*unidades.
Tanto el nmero de unidades que vendemos como el precio
vendrn establecidos por la curva de la demanda de telfonos
mviles.

Precios diferentes: Podemos descomponer la demanda en


funcin del tipo de clientes al que nos dirigimos, de tal forma
que obtenemos dos curvas de demanda, una para profesionales
autnomos y otra para estudiantes:

demandatotal = demandaautnomos+demandaestudiantes
Si suponemos que la empresa de telecomunicaciones tiene que invertir
100M en poner en marcha la red UMTS y el coste marginal de un
telfono mvil supone slo 5, calcule cul es el precio al que habra que
vender los mviles si la demanda fuese:
precio(cantidad) = 300 c/40000

Podemos descomponer la demanda en dos segmentos:


precioestudiante(cantidad) = 100 cantidad/50000
precioautnomo(cantidad) = 200 cantidad/200000
Ahora, podemos analizar cul sera el precio ideal al que tendramos que
venderle un telfono a un estudiante y cul sera el precio al que
deberamos ofrecerle un telfono a un profesional autnomo (por qu no
son iguales estos precios?).
Por tanto, disponemos de dos estrategias para establecer los precios de
los nuevos telfonos mviles:
- Cmo vender ms mviles la empresa de telecomunicaciones?
- Cmo ganar ms dinero la empresa de telecomunicaciones?
Implemente en Java el proceso que hemos seguido para calcular las
consecuencias de las distintas estrategias y poder analizar las situaciones
que podran llegar a producirse si cambiase la demanda de telfonos
mviles UMTS.

CUESTIONES PARA ANALIZAR CON MAYOR DETENIMIENTO:


Qu estrategias utiliza la empresa de telecomunicaciones para
convencer a sus clientes de que deben pagar precios diferentes por
el mismo servicio? Estn los autnomos subvencionando el uso
de mviles por parte de los estudiantes? Cmo se consigue
eliminar de los autnomos la percepcin de que pagan ms de lo
que podran estar pagando?
Por qu se venden ms caros los accesorios de un mvil en
proporcin a su coste con respecto al precio al que se vende el
mvil en s?
Por qu las lneas areas cobran menos dinero por un billete de
ida y vuelta si pasamos el fin de semana en el destino?
Por qu se edita el mismo libro con distintas encuadernaciones y
se cobra ms por la edicin con las tapas duras aunque el
contenido del libro siga siendo el mismo?

Estructuras de control
Programacin estructurada
Estructuras condicionales
La sentencia if
La clusula else
Encadenamiento y anidamiento
El operador condicional ?:
La sentencia switch
Estructuras repetitivas/iterativas
El bucle while
El bucle for
El bucle dowhile
Bucles anidados
Cuestiones de estilo

Las estructuras de control


controlan la ejecucin de las instrucciones de un programa
(especifican el orden en el que se realizan las acciones)

Estructuras de control

-0-

Fernando Berzal

Programacin estructurada
IDEA CENTRAL:
Las estructuras de control de un programa
slo deben tener un punto de entrada y un punto de salida.

La programacin estructurada...
mejora la productividad de los programadores.
mejora la legibilidad del cdigo resultante.

La ejecucin de un programa estructurado progresa disciplinadamente,


en vez de saltar de un sitio a otro de forma impredecible

Gracias a ello, los programas


resultan ms fciles de probar
se pueden depurar ms fcilmente
se pueden modificar con mayor comodidad

Estructuras de control: Java

-1-

Fernando Berzal

En programacin estructurada slo se emplean tres construcciones:

Secuencia
Conjunto de sentencias que se ejecutan en orden
Ejemplos:
Sentencias de asignacin y llamadas a rutinas.

Seleccin
Elige qu sentencias se ejecutan en funcin de una condicin.
Ejemplos:
Estructuras de control condicional if-then-else y case/switch

Iteracin
Las estructuras de control repetitivas repiten conjuntos de
instrucciones.
Ejemplos:
Bucles while, do...while y for.

Teorema de Bhm y Jacopini (1966):


Cualquier programa de ordenador
puede disearse e implementarse
utilizando nicamente las tres construcciones estructuradas
(secuencia, seleccin e iteracin; esto es, sin sentencias goto).

Bhm, C. & Jacopini, G.: Flow diagrams, Turing machines, and languages only with two
formation rules. Communications of the ACM, 1966, Vol. 9, No. 5, pp. 366-371
Dijkstra, E.W.: Goto statement considered harmful. Communications of the ACM, 1968, Vol.
11, No. 3, pp. 147-148

Estructuras de control: Java

-2-

Fernando Berzal

Estructuras de control
condicionales
Por defecto,
las instrucciones de un programa se ejecutan secuencialmente:

El orden secuencial de ejecucin no altera el flujo de control


del programa respecto al orden de escritura de las instrucciones.

Sin embargo, al describir la resolucin de un problema, es normal que


tengamos que tener en cuenta condiciones que influyen sobre la
secuencia de pasos que hay que dar para resolver el problema:

Segn se cumplan o no determinadas condiciones,


la secuencia de pasos involucrada en la realizacin de una tarea ser
diferente

Las estructuras de control condicionales o selectivas nos permiten


decidir qu ejecutar y qu no en un programa.

Ejemplo tpico
Realizar una divisin slo si el divisor es distinto de cero.

Estructuras de control: Java

-3-

Fernando Berzal

La estructura de control condicional if


La sentencia if nos permite elegir
si se ejecuta o no un bloque de instrucciones.

Sintaxis
if (condicin)
sentencia;

if (condicin) {
bloque
}

donde bloque representa un bloque de instrucciones.

Bloque de instrucciones:
Secuencia de instrucciones encerradas entre dos llaves {....}

Estructuras de control: Java

-4-

Fernando Berzal

Consideraciones acerca del uso de la sentencia if


- Olvidar los parntesis al poner la condicin del if es un error
sintctico (los parntesis son necesarios)
- No hay que confundir el operador de comparacin ==
con el operador de asignacin =
- Los operadores de comparacin ==, !=, <= y >= han de escribirse
sin espacios.
- => y =< no son operadores vlidos en Java.
- El fragmento de cdigo afectado por la condicin del if debe
sangrarse para que visualmente se interprete correctamente el
mbito de la sentencia if:
if (condicin) {
// Aqu se incluye el cdigo
// que ha de ejecutarse
// cuando se cumple la condicin del if
}

- Aunque el uso de llaves no sea obligatorio cuando el if slo


afecta a una sentencia, es recomendable ponerlas siempre para
delimitar explcitamente el mbito de la sentencia if.

Error comn:
if (condicin);
sentencia;

es interpretado como
if (condicin)
;
// Sentencia vaca
sentencia;

La sentencia siempre se ejecutara!!!


Estructuras de control: Java

-5-

Fernando Berzal

Ejemplo
Comparacin de nmeros (Deitel & Deitel)
Operador
==
!=
<
>
<=
>=

Significado
Igual
Distinto
Menor
Mayor
Menor o igual
Mayor o igual

import javax.swing.JOptionPane;
public class Comparison
{
public static void main( String args[] )
{
// Declaracin de variables
String primerDato, segundoDato;
String resultado;
int
dato1, dato2;

primerDato

= JOptionPane.showInputDialog
( "Primer dato:" );
segundoDato = JOptionPane.showInputDialog
( "Segundo dato:" );
dato1 = Integer.parseInt( primerDato );
dato2 = Integer.parseInt( segundoDato );
resultado = "";
if ( dato1 == dato2 )
resultado += dato1 + " == " + dato2;
if ( dato1 != dato2 )
resultado += dato1 + " != " + dato2;

Estructuras de control: Java

-6-

Fernando Berzal

if ( dato1 < dato2 )


resultado += "\n" + dato1 + " < " + dato2;
if ( dato1 > dato2 )
resultado += "\n" + dato1 + " > " + dato2;
if ( dato1 <= dato2 )
resultado += "\n" + dato1 + " <= " + dato2;
if ( dato1 >= dato2 )
resultado += "\n" + dato1 + " >= " + dato2;
JOptionPane.showMessageDialog
( null, resultado,
"Resultados de la comparacin",
JOptionPane.INFORMATION_MESSAGE );
System.exit( 0 );
}
}

Estructuras de control: Java

-7-

Fernando Berzal

La clusula else
Una sentencia if, cuando incluye la clusula else,
permite ejecutar un bloque de cdigo si se cumple la condicin
y otro bloque de cdigo diferente si la condicin no se cumple.

Sintaxis
if (condicin)
sentencia1;
else
sentencia2;

if (condicin) {
bloque1
} else {
bloque2
}

Los bloques de cdigo especificados


representan dos alternativas complementarias y excluyentes

Estructuras de control: Java

-8-

Fernando Berzal

Ejemplo
import javax.swing.JOptionPane;
public class IfElse
{
public static void main( String args[] )
{
String primerDato, segundoDato;
String resultado;
int
dato1, dato2;
primerDato

= JOptionPane.showInputDialog
( "Primer dato:" );
segundoDato = JOptionPane.showInputDialog
( "Segundo dato:" );
dato1 = Integer.parseInt( primerDato );
dato2 = Integer.parseInt( segundoDato );
resultado = "";
if ( dato1 == dato2 )
resultado += dato1 + " == " + dato2;
else
resultado += dato1 + " != " + dato2;
if ( dato1 < dato2 )
resultado += "\n" + dato1 + " < " + dato2;
else
resultado += "\n" + dato1 + " >= " + dato2;
if ( dato1 > dato2 )
resultado += "\n" + dato1 + " > " + dato2;
else
resultado += "\n" + dato1 + " <= " + dato2;
JOptionPane.showMessageDialog
( null, resultado,
"Resultados de la comparacin",
JOptionPane.INFORMATION_MESSAGE );
System.exit( 0 );
}
}

Estructuras de control: Java

-9-

Fernando Berzal

Con esta versin del programa de comparacin de nmeros


obtenemos los mismos resultados que antes,
si bien nos ahorramos tres comparaciones:

La sentencia
if (condicin)
sentencia1;
else
sentencia2;

es equivalente a
if (condicin)
sentencia1;
if (!condicin)
sentencia2;

Estructuras de control: Java

- 10 -

Fernando Berzal

Nota acerca de la comparacin de objetos


Cuando el operador == se utiliza para comparar objetos,
lo que se compara son las referencias a los objetos
y no el estado de los objetos en s.
Ejemplo
public class Complex
{
private double real;
private double imag;
// Constructor
public Complex (double real, double imag)
{
this.real = real;
this.imag = imag;
}
// equals se suele definir para comparar objetos
public boolean equals (Complex c)
{
return (this.real == c.real)
&& (this.imag == c.imag);
}
}
...
Complex c1 = new Complex(2,1);
Complex c2 = new Complex(2,1);
if (c1 == c2)
System.out.println("Las referencias son iguales");
else
System.out.println("Las referencias no son iguales");
if (c1.equals(c2))
System.out.println("Los objetos son iguales");
else
System.out.println("Los objetos no son iguales");
Estructuras de control: Java

- 11 -

Fernando Berzal

Encadenamiento
Las sentencias if se suelen encadenar:

if else if

import javax.swing.JOptionPane;
public class IfChain
{
public static void main( String args[] )
{
String entrada;
String resultado;
float nota;

entrada = JOptionPane.showInputDialog
( "Calificacin numrica:" );
nota = Float.parseFloat( entrada );

if ( nota >= 9
resultado =
else if ( nota
resultado =
else if ( nota
resultado =
else
resultado =

)
"Sobresaliente";
>= 7 )
"Notable";
>= 5 )
"Aprobado";
"Suspenso";

JOptionPane.showMessageDialog
( null, resultado,
"Calificacin final",
JOptionPane.INFORMATION_MESSAGE );
System.exit( 0 );
}
}

Estructuras de control: Java

- 12 -

Fernando Berzal

El if encadenado anterior equivale a:


import javax.swing.JOptionPane;
public class IfChain2
{
public static void main( String args[] )
{
String entrada;
String resultado;
float nota;

entrada = JOptionPane.showInputDialog
( "Calificacin numrica:" );
nota = Float.parseFloat( entrada );

resultado = ;
if ( nota >= 9 )
resultado = "Sobresaliente";
if ( (nota>=7) && (nota<9) )
resultado = "Notable";
if ( (nota>=5) && (nota<7) )
resultado = "Aprobado";
if ( nota < 5 )
resultado = "Suspenso";

JOptionPane.showMessageDialog
( null, resultado,
"Calificacin final",
JOptionPane.INFORMATION_MESSAGE );
System.exit( 0 );
}
}

Estructuras de control: Java

- 13 -

Fernando Berzal

Anidamiento
Las sentencias if tambin se pueden anidar unas dentro de otras.

Ejemplo: Resolucin de una ecuacin de primer grado ax+b=0


import javax.swing.JOptionPane;
public class IfNested
{
public static void main( String args[] )
{
String entrada;
String resultado;
float a,b,x;
entrada = JOptionPane.showInputDialog
( Coeficiente a );
a = Float.parseFloat( entrada );
entrada = JOptionPane.showInputDialog
( Coeficiente b );
b = Float.parseFloat( entrada );
if (a!=0) {
x = -b/a;
resultado = "La solucin es " + x;
} else {
if (b!=0) {
resultado = "No tiene solucin.";
} else {
resultado = "Solucin indeterminada.";
}
}
JOptionPane.showMessageDialog
( null, resultado,
"Solucin de la ecuacin de primer grado",
JOptionPane.INFORMATION_MESSAGE );
System.exit( 0 );
}
}
Estructuras de control: Java

- 14 -

Fernando Berzal

El if anidado anterior equivale a


import javax.swing.JOptionPane;
public class IfNested2
{
public static void main( String args[] )
{
String entrada;
String resultado;
float a,b,x;
entrada = JOptionPane.showInputDialog
( Coeficiente a );
a = Float.parseFloat( entrada );
entrada = JOptionPane.showInputDialog
( Coeficiente b );
b = Float.parseFloat( entrada );
resultado = "";
if (a!=0) {
x = -b/a;
resultado = "La solucin es " + x;
}
if ( (a==0) && (b!=0) ) {
resultado = "No tiene solucin.";
}
if ( (a==0) && (b==0) ) {
resultado = "Solucin indeterminada.";
}
JOptionPane.showMessageDialog
( null, resultado,
"Solucin de la ecuacin de primer grado",
JOptionPane.INFORMATION_MESSAGE );
System.exit( 0 );
}
}

En este caso, se realizan 5 comparaciones en vez de 2.

Estructuras de control: Java

- 15 -

Fernando Berzal

El operador condicional ?:
Java proporciona una forma de abreviar una sentencia if

El operador condicional ?:
permite incluir una condicin dentro de una expresin.

Sintaxis
variable = condicin? expresin1: expresin2;

equivale a
if (condicin)
variable = expresin1;
else
variable = expresin2;

Slo se evala una de las expresiones,


por lo que deberemos ser cuidadosos con los efectos colaterales.

Ejemplos
max = (x>y)? x : y;
min = (x<y)? x : y;
med = (x<y)? ((y<z)? y: ((z<x)? x: z)):
((x<z)? x: ((z<y)? y: z));
nick = (nombre!=null)? nombre : desconocido;

Estructuras de control: Java

- 16 -

Fernando Berzal

Seleccin mltiple con la sentencia switch


Permite seleccionar entre varias alternativas posibles
Sintaxis
switch (expresin) {
case expr_cte1:
bloque1;
break;
case expr_cte2:
bloque2;
break;
...
case expr_cteN:
bloqueN;
break;
default:
bloque_por_defecto;
}

Se selecciona a partir de la evaluacin de una nica expresin.


La expresin del switch ha de ser de tipo entero (int).
Los valores de cada caso del switch han de ser constantes.
En Java, cada bloque de cdigo de los que acompaan a un posible
valor de la expresin entera ha de terminar con una sentencia break;
La etiqueta default marca el bloque de cdigo que se ejecuta por
defecto (cuando al evaluar la expresin se obtiene un valor no
especificado por los casos anteriores del switch).
En Java, se pueden poner varias etiquetas seguidas acompaando a
un nico fragmento de cdigo si el fragmento de cdigo que ha de
ejecutarse es el mismo para varios valores de la expresin entera que
gobierna la ejecucin del switch.

Estructuras de control: Java

- 17 -

Fernando Berzal

Ejemplo
public class Switch
{
public static void main( String args[] )
{
String resultado;
int
nota;
// Entrada de datos

switch
case
case
case
case
case

(nota) {
0:
1:
2:
3:
4:
resultado = "Suspenso";
break;

case 5:
case 6:
resultado = "Aprobado";
break;
case 7:
case 8:
resultado = "Notable";
break;
case 9:
case 10:
resultado = "Sobresaliente";
break;
default:
resultado = "Error";
}
// Salida de resultados

}
}

Si tuvisemos que trabajar con datos de tipo real,


no podramos usar switch (usaramos ifs encadenados).
Estructuras de control: Java

- 18 -

Fernando Berzal

Estructuras de control
repetitivas/iterativas
repetitivas/iterativas
A menudo es necesario ejecutar
una instruccin o un bloque de instrucciones ms de una vez.
Ejemplo
Implementar un programa que calcule
la suma de N nmeros ledos desde teclado.

Podramos escribir un programa en el que apareciese repetido el cdigo


que deseamos que se ejecute varias veces, pero
Nuestro programa podra ser demasiado largo.
Gran parte del cdigo del programa estara duplicado, lo que
dificultara su mantenimiento en caso de que tuvisemos que hacer
cualquier cambio, por trivial que fuese ste.
Una vez escrito el programa para un nmero determinado de
repeticiones (p.ej. sumar matrices 3x3), el mismo programa no
podramos reutilizarlo si necesitsemos realizar un nmero
distinto de operaciones (p.ej. sumar matrices 4x4).

Las estructuras de control repetitivas o iterativas, tambin conocidas


como bucles, nos permiten resolver de forma elegante este tipo de
problemas. Algunas podemos usarlas cuando conocemos el nmero de
veces que deben repetirse las operaciones. Otras nos permiten repetir un
conjunto de operaciones mientras se cumpla una condicin.

Iteracin: Cada repeticin de las instrucciones de un bucle.

Estructuras de control: Java

- 19 -

Fernando Berzal

El bucle while
Permite repetir la ejecucin de un conjunto de sentencias
mientras se cumpla una condicin:
while (condicin)
sentencia;

while (condicin) {
bloque
}

El bucle while terminar su ejecucin


cuando deje de verificarse la condicin que controla su ejecucin.
Si, inicialmente, no se cumple la condicin,
el cuerpo del bucle no llegar a ejecutarse.
MUY IMPORTANTE
En el cuerpo del bucle debe existir algo que haga variar el valor
asociado a la condicin que gobierna la ejecucin del bucle.

Estructuras de control: Java

- 20 -

Fernando Berzal

Ejemplo
Tabla de multiplicar de un nmero
public class While1
{
public static void main( String args[] )
{
int n; // Nmero
int i; // Contador
n = Integer.parseInt( args[0] );
i = 0;
while (i<=10) {
System.out.println (n+" x "+i+" = "+(n*i));
i++;
}
}
}

Ejemplo
Divisores de un nmero
public class While2
{
public static void main( String args[] )
{
int n;
int divisor;
n = Integer.parseInt( args[0] );
System.out.println("Los divisores son:");
divisor = n;
while (divisor>0) {
if ((n%divisor) == 0)
System.out.println(divisor);
divisor--;
}
}
}
Estructuras de control: Java

- 21 -

Fernando Berzal

En los ejemplos anteriores,


se conoce de antemano el nmero de iteraciones
que han de realizarse (cuntas veces se debe ejecutar el bucle):

La expresin del while se convierte en una simple


comprobacin del valor de una variable contador.

El contador es una variable que se incrementa o decrementa en


cada iteracin y nos permite saber la iteracin en la que
nos
encontramos en cada momento.

En el cuerpo del bucle, siempre se incluye una sentencia


contador++;

o bien
contador--;

para que, eventualmente,


la condicin del while deje de cumplirse.

En otras ocasiones, puede que no conozcamos de antemano cuntas


iteraciones se han de realizar.

La condicin del while puede que tenga un aspecto diferente


pero, en el cuerpo del bucle, deber seguir existiendo algo que
modifique el resultado de evaluar la condicin.

Estructuras de control: Java

- 22 -

Fernando Berzal

Ejemplo
Sumar una serie de nmeros
hasta que el usuario introduzca un cero
import javax.swing.JOptionPane;
public class While3
{
public static void main( String args[] )
{
float valor;
float suma;
suma = 0;
valor = leerValor();
while (valor!=0) {
suma += valor;
valor = leerValor();
}
mostrarValor("Suma de los datos", suma);
System.exit(0);
}
private static float leerValor ()
{
String entrada;
entrada = JOptionPane.showInputDialog
( "Introduzca un dato:" );
return Float.parseFloat(entrada);
}
private static void mostrarValor
(String mensaje, float valor)
{
JOptionPane.showMessageDialog
( null, valor, mensaje,
JOptionPane.INFORMATION_MESSAGE );
}
}

El valor introducido determina en cada iteracin


si se termina o no la ejecucin del bucle.
Estructuras de control: Java

- 23 -

Fernando Berzal

El bucle for
Se suele emplear en sustitucin del bucle while
cuando se conoce el nmero de iteraciones que hay que realizar.
Sintaxis
for (expr1; expr2; expr3) {
bloque;
}

Estructuras de control: Java

- 24 -

Fernando Berzal

Equivalencia entre for y while


Un fragmento de cdigo
como el que apareca antes con un bucle while:
i = 0;
while (i<=10) {
System.out.println (n+" x "+i+" = "+(n*i));
i++;
}

puede abreviarse si utilizamos un bucle for:


for (i=0; i<=10; i++) {
System.out.println (n+" x "+i+" = "+(n*i));
}

Como este tipo de estructuras de control es muy comn,


el lenguaje nos ofrece una forma ms compacta
de representar un bucle cuando sabemos
cuntas veces ha de ejecutarse el cuerpo del bucle.

En general,
for (expr1; expr2; expr3) {
bloque;
}

equivale a
expr1;
while (expr2) {
bloque;
expr3;
}

Estructuras de control: Java

- 25 -

Fernando Berzal

Ejemplo
Clculo del factorial de un nmero
Bucle for
public class FactorialFor
{
public static void main( String args[] )
{
long i,n,factorial;
n = Integer.parseInt( args[0] );
factorial = 1;
for (i=1; i<=n; i++) {
factorial *= i;
}
System.out.println ( "f("+n+") = " + factorial);
}
}
Bucle while
public class FactorialWhile
{
public static void main( String args[] )
{
long i,n,factorial;
n = Integer.parseInt( args[0] );
factorial = 1;
i = 1;
while (i<=n) {
factorial *= i;
i++;
}
System.out.println ( "f("+n+") = " + factorial);
}
}
Estructuras de control: Java

- 26 -

Fernando Berzal

for (expr1; expr2; expr3) {


bloque;
}

En un bucle for
La primera expresin, expr1, suele contener inicializaciones de
variables separadas por comas. En particular, siempre aparecer la
inicializacin de la variable que hace de contador.
o Las instrucciones que se encuentran en esta parte del for slo
se ejecutarn una vez antes de la primera ejecucin del cuerpo
del bucle (bloque).
La segunda expresin, expr2, es la que contiene una expresin
booleana (la que aparecera en la condicin del bucle while
equivalente para controlar la ejecucin del cuerpo del bucle).
La tercera expresin, expr3, contiene las instrucciones, separadas
por comas, que se deben ejecutar al finalizar cada iteracin del bucle
(p.ej. el incremento/decremento de la variable contador).
El bloque de instrucciones bloque es el mbito del bucle (el bloque
de instrucciones que se ejecuta en cada iteracin).

Estructuras de control: Java

- 27 -

Fernando Berzal

for (i=0; i<N; i++)

Nmero de
iteraciones
N

for (i=0; i<=N; i++)

N+1

for (i=k; i<N; i++)

N-k

for (i=N; i>0; i--)

for (i=N; i>=0; i--)

N+1

for (i=N; i>k; i--)

N-k

for (i=0; i<N; i+=k)

N/k

for (i=j; i<N; i+=k)

(N-j)/k

for (i=1; i<N; i*=2)

log2 N

for (i=0; i<N; i*=2)

for (i=N; i>0; i/=2)

log2 N + 1

Cabecera del bucle

suponiendo que N y k sean enteros positivos

Bucles infinitos
Un bucle infinito es un bucle que se repite infinitas veces:
for (;;)

/*bucle infinito*/

while (true)

/*bucle infinito*/

Si nunca deja de cumplirse la condicin del bucle,


nuestro programa se quedar indefinidamente
ejecutando el cuerpo del bucle, sin llegar a salir de l.

Estructuras de control: Java

- 28 -

Fernando Berzal

El bucle do while
Tipo de bucle, similar al while, que realiza la comprobacin de la
condicin despus de ejecutar el cuerpo del bucle.
Sintaxis
do
sentencia;
while (condicin);

do {
bloque
} while (condicin);

El bloque de instrucciones se ejecuta, al menos, una vez.


El bucle do while resulta especialmente indicado para validar datos de
entrada (comprobar que los valores de entrada obtenidos estn dentro
del rango de valores que el programa espera).
En todos nuestros programas debemos asegurarnos
de que se obtienen datos de entrada vlidos
antes de realizar cualquier tipo de operacin con ellos.
Estructuras de control: Java

- 29 -

Fernando Berzal

Ejemplo
Clculo del factorial
comprobando el valor del dato de entrada
import javax.swing.JOptionPane;
public class FactorialDoWhile
{
public static void main( String args[] )
{
long n;
do {
n = leerEntero(0,20);
} while ((n<0) || (n>20));
mostrarMensaje ( "f("+n+") = "+ factorial(n));
System.exit(0);
}
private static long factorial (long n)
{
long i;
long factorial = 1;
for (i=1; i<=n; i++) {
factorial *= i;
}
return factorial;
}
private static int leerEntero (int min, int max)
{
String entrada = JOptionPane.showInputDialog
( "Introduzca un valor entero
+ (entre "+min+" y "+max+"): );
return Integer.parseInt(entrada);
}
private static void mostrarMensaje (String mensaje)
{
JOptionPane.showMessageDialog(null,mensaje);
}
}

Estructuras de control: Java

- 30 -

Fernando Berzal

Ejemplo
Clculo de la raz cuadrada de un nmero
import javax.swing.JOptionPane;
public class Sqrt
{
public static void main( String args[] )
{
double n;
do {
n = leerReal ("Introduzca un nmero positivo");
} while (n<0);
mostrarMensaje( "La raz cuadrada de "+n
+ " es aproximadamente "+raiz(n));
System.exit(0);
}
private static double raiz (double n)
{
double r;
// Raz cuadrada del nmero
double prev; // Aproximacin previa de la raz
r = n/2;
do {
prev = r;
r = (r+n/r)/2;
} while (Math.abs(r-prev) > 1e-6);
return r;
}
private static double leerReal (String mensaje)
{
String entrada;
entrada = JOptionPane.showInputDialog(mensaje);
return Double.parseDouble(entrada);
}
private static void mostrarMensaje (String mensaje)
{
JOptionPane.showMessageDialog(null,mensaje);
}
}
Estructuras de control: Java

- 31 -

Fernando Berzal

Bucles anidados
Los bucles tambin se pueden anidar:

for (i=0; i<N;i++) {


for (j=0; j<N; j++) {
printf((%d,%d) ,i,j);
}
}

genera como resultado:


(0,0) (0,1) (0,2) (0,N)
(1,0) (1,1) (1,2) (1,N)

(N,0) (N,1) (N,2) (N,N)

Ejemplo
int n,i,k;

n = 0;

// Paso 1

for (i=1; i<=2; i++) {

// Paso 2

for (k=5; k>=1; k-=2) {

// Paso 3

n = n + i + k;

// Paso 4

// Paso 5

// Paso 6

// Paso 7

Paso

10

12

19

24

2
5

Estructuras de control: Java

3
5

- 32 -

27

Fernando Berzal

Cuestiones de estilo
Escribimos cdigo para que lo puedan leer otras personas,
no slo para que lo traduzca el compilador.

Identificadores
q

Los identificadores deben ser descriptivos

p, i, s...
precio, izquierda, suma...

En ocasiones, se permite el uso de nombres cortos para variables


locales cuyo significado es evidente (p.ej. bucles controlados por
contador)
for (elemento=0; elemento<N; elemento++ )
for (i=0; i<N; i++)

Constantes
q

Se considera una mala costumbre incluir literales de tipo numrico


(nmeros mgicos) en medio del cdigo. Se prefiere la definicin
de constantes simblicas (con final).

for (i=0; i<79; i++)


for (i=0; i<columnas-1; i++)

Estructuras de control: Java

- 33 -

Fernando Berzal

Expresiones
q

Expresiones booleanas:
Es aconsejable escribirlas como se diran en voz alta.

if ( !(bloque<actual) )
if ( bloque >= actual )

Expresiones complejas:
Es aconsejable dividirlas para mejorar su legibilidad

x += ( xp = ( 2*k<(n-m) ? c+k: d-k ));


if ( 2*k < n-m )
xp = c+k;
else
xp = d-k;
x += xp;

max = (a > b) ? a : b;

Comentarios
q

Comentarios descriptivos: Los comentarios deben comunicar algo.


Jams se utilizarn para parafrasear el cdigo y repetir lo que es
obvio.

i++;

/* Incrementa el contador */

/* Recorrido secuencial de los datos*/


for (i=0; i<N; i++) ...

Estructuras de control: Java

- 34 -

Fernando Berzal

Estructuras de control
q

Sangras:
Conviene utilizar espacios en blanco o separadores para delimitar
el mbito de las estructuras de control de nuestros programas.
Lneas en blanco:
Para delimitar claramente los distintos bloques de cdigo
en nuestros programas dejaremos lneas en blanco entre ellos.
Salvo en la cabecera de los bucles for,
slo incluiremos una sentencia por lnea de cdigo.
Sean cuales sean las convenciones utilizadas al escribir cdigo (p.ej.
uso de sangras y llaves), hay que ser consistente en su utilizacin.
while () {

while ()
{

for (;;) {

for (;;)
{

if () {

if ()
{

El cdigo bien escrito es ms fcil de leer, entender y mantener


(adems, seguramente tiene menos errores)

Estructuras de control: Java

- 35 -

Fernando Berzal

Estructuras de control
Relacin de ejercicios
1. Cuntas veces se ejecutara el cuerpo de los siguientes bucles for?
for (i=1; i<10; i++)
for (i=30; i>1; i-=2)
for (i=30; i<1; i+=2)
for (i=0; i<30; i+=4)

2. Ejecute paso a paso el siguiente bucle:


c = 5;
for (a=1; a<5; a++)
c = c 1;

3. Escriba un programa que lea una serie de N datos y nos muestre: el nmero de
datos introducidos, la suma de los valores de los datos, la media del conjunto de
datos, el mximo, el mnimo, la varianza y la desviacin tpica.
PISTA: La varianza se puede calcular a partir de
la suma de los cuadrados de los datos.

4. Disee un programa que lea los coeficientes de una ecuacin de segundo grado
ax2+bx+c=0 y calcule sus dos soluciones. El programa debe responder de forma
adecuada para cualquier caso que se pueda presentar.
5. Disee un programa que lea los coeficientes de un sistema de dos ecuaciones
lineales con dos incgnitas y calcule su solucin. El programa debe responder de
forma adecuada cuando el sistema de ecuaciones no sea compatible
determinado.
ax + by = c

dx + ey = f

6. Dada una medida de tiempo expresada en horas, minutos y segundos con valores
arbitrarios, elabore un programa que transforme dicha medida en una expresin
correcta. Por ejemplo, dada la medida 3h 118m 195s, el programa deber
obtener como resultado 5h 1m 15s. Realice el programa sin utilizar los
operadores de divisin entera (/ y %).
7. Escriba un programa en C que nos calcule el cambio que debe dar la caja de un
supermercado: Dado un precio y una cantidad de dinero, el programa nos dir
cuntas monedas deben darse como cambio de tal forma que el nmero total de
monedas sea mnimo. Realice el programa sin utilizar los operadores de divisin
entera (/ y %).
8. Implemente un programa que lea un nmero decimal y lo muestre en pantalla en
hexadecimal (base 16). El cambio de base se realiza mediante divisiones
sucesivas por 16 en las cuales los restos determinan los dgitos hexadecimales
del nmero segn la siguiente correspondencia:
Resto
Dgito

0
0

1
1

2
2

3
3

4
4

5
5

6
6

7
7

8
8

9
9

10 11 12 13 14 15
A B C D E F

Por ejemplo:

65029|10 = FE05|16
9. Escriba una funcin (un mtodo) que obtenga la letra del DNI a partir del
nmero. Para ello debe obtener el resto de dividir el nmero entre 23. La letra
asociada al nmero vendr dada por este resto en funcin de la siguiente tabla:
0T
6Y
12 N
18 H

1R
7F
13 J
19 L

2W
8P
14 Z
20 C

3A
9D
15 S
21 K

4G
10 X
16 Q
22 E

5M
11 B
17 V
23 T

10. Escriba una funcin que, a partir de los dgitos de un ISBN, calcule el carcter
de control con el que termina todo ISBN. Para calcular el carcter de control,
debe multiplicar cada dgito por su posicin (siendo el dgito de la izquierda el
que ocupa la posicin 1), sumar los resultados obtenidos y hallar el resto de
dividir por 11. El resultado ser el carcter de control, teniendo en cuenta que el
carcter de control es X cuando el resto vale 10.

11. Implemente un programa que calcule la suma de los 100 primeros trminos de
las siguientes sucesiones:
a n = a n 1 + n
a n 1
n
n2 1
a n = (1) n
2n + 1
an =

12. Realice un programa que calcule los valores de la funcin:


x
f ( x, y ) = 2
y 1
para los valores de (x,y) con x=-50,-48048,50 e y=-40,-39039,40
n
13. Implemente funciones que nos permitan calcular xn, n! y
m
14. Escriba un programa que muestre en pantalla todos los nmeros primos entre 1 y
n, donde n es un nmero positivo que recibe el programa como parmetro.
15. Escriba una funcin que, dados dos nmeros enteros, nos diga si cualquiera de
ellos divide o no al otro.
16. Implemente un programa que calcule los divisores de un nmero entero.
17. Implemente una funcin que nos devuelva el mximo comn divisor de dos
nmeros enteros.
18. Implemente una funcin que nos devuelva el mnimo comn mltiplo de dos
nmeros enteros.
19. Disee e implemente un programa que realice la descomposicin en nmeros
primos de un nmero entero.
20. Escriba un programa que lea nmeros enteros hasta que se introduzcan 10
nmeros o se introduzca un valor negativo. El programa mostrar entonces el
valor medio de los nmeros introducidos (sin contar el nmero negativo en caso
de que ste se haya indicado).
21. Implemente una funcin que nos diga si un nmero ha conseguido o no el
reintegro en el sorteo de la ONCE. Un nmero de cinco cifras consigue el
reintegro si su primera o ltima cifra coincide con la primera o ltima cifra del
nmero agraciado en el sorteo.
22. Disee un programa para jugar a adivinar un nmero entre 0 y 100. El programa
ir dando pistas al jugador indicndole si el nmero introducido por el jugador
es menor o mayor que el nmero que tiene que adivinar. El juego termina
cuando el jugador adivina el nmero o decide terminar de jugar (por ejemplo,
escribiendo un nmero negativo).

23. Ample el programa del ejercicio anterior permitiendo que el jugador juegue
tantas veces como desee. El programa deber mantener las estadsticas del
jugador y mostrrselas al final de cada partida (nmero medio de intentos para
adivinar el nmero, nmero de veces que el jugador abandona, mejor partida y
peor partida).

24. Aplicar el mtodo de Newton-Raphson a los siguientes problemas:


a. Calcular la raz cuadrada de un nmero.
b. Calcular la raz cbica de un nmero.
c. Calcular la raz n-sima de un nmero
El mtodo de Newton-Raphson en un mtodo general para la obtencin de los
ceros de una funcin. Para ello se van generando los trminos de la sucesin
f ( xi )
x n +1 = xi
f ' ( xi )
donde f(x) es la funcin cuyo cero deseamos obtener y f(x) es la derivada de la
funcin. Por ejemplo, para calcular la raz cuadrada de un nmero n, hemos de
obtener un cero de la funcin f(x) = x2-n
Partiendo de un valor inicial x0 cualquiera, se van generando trminos de la
sucesin hasta que la diferencia entre dos trminos consecutivos de la sucesin
sea inferior a una precisin especificada de antemano (p.ej. 10-6) .

25. Uso y manipulacin de fechas:


a. Disee una clase para representar fechas.
b. Escriba un mtodo esttico que nos diga el nmero de das de un mes
(ojo con los aos bisiestos!).
c. Aada a su clase un mtodo que nos indique el nmero de das del mes al
que pertenece la fecha.
d. Incluya, en su clase Fecha, un mtodo que nos diga el nmero de das
que hay desde una fecha determinada hasta otra.
e. Implemente un mtodo que nos diga el da de la semana correspondiente
a una fecha concreta (p.ej. el 1 de diciembre de 2004 fue mircoles).
f. Escriba un programa que muestre el calendario de un mes concreto.
NOTA: Compruebe el correcto funcionamiento de todos los programas con varios
valores para sus entradas. En el caso de los ejercicios en que se pide la creacin de un
mtodo o funcin, escriba programas auxiliares que hagan uso del mtodo creado.

Vectores y matrices
Arrays
Declaracin
Creacin
Acceso a los elementos de un array
Manipulacin de vectores y matrices
Algoritmos de ordenacin
Ordenacin por seleccin
Ordenacin por insercin
Ordenacin por intercambio directo (mtodo de la burbuja)
Ordenacin rpida (QuickSort)
Algoritmos de bsqueda
Bsqueda lineal
Bsqueda binaria
Apndice: Cadenas de caracteres

Vectores y matrices - Java

-0-

Fernando Berzal

Arrays
Un array es una estructura de datos
que contiene una coleccin de datos del mismo tipo

Ejemplos
Temperaturas mnimas de los ltimos treinta das
Valor de las acciones de una empresa durante la ltima semana

Propiedades de los arrays


- Los arrays se utilizan como contenedores para almacenar datos
relacionados (en vez de declarar variables por separado para cada
uno de los elementos del array).
- Todos los datos incluidos en el array son del mismo tipo. Se
pueden crear arrays de enteros de tipo int o de reales de tipo
float, pero en un mismo array no se pueden mezclar datos de
tipo int y datos de tipo float.
- El tamao del array se establece cuando se crea el array (con el
operador new, igual que cualquier otro objeto).
- A los elementos del array se acceder a travs de la posicin que
ocupan dentro del conjunto de elementos del array.

Terminologa
Los arrays unidimensionales se conocen con el nombre de vectores.
Los arrays bidimensionales se conocen con el nombre de matrices.
Vectores y matrices - Java

-1-

Fernando Berzal

Declaracin
Para declarar un array,
se utilizan corchetes para indicar que se trata de un array
y no de una simple variable del tipo especificado.

Vector (array unidimensional):


tipo identificador[];

o bien
tipo[] identificador;

donde
tipo es el tipo de dato de los elementos del vector
identificador es el identificador de la variable.

Matriz (array bidimensional):


tipo identificador[][];

o bien
tipo[][] identificador;

NOTA: No es una buena idea que el identificador del array


termine en un dgito, p.ej. vector3
Vectores y matrices - Java

-2-

Fernando Berzal

Creacin
Los arrays se crean con el operador new.

Vector (array unidimensional):


vector = new tipo[elementos];

Entre corchetes se indica el tamao del vector.


tipo debe coincidir con el tipo con el que se haya declarado el vector.
vector debe ser una variable declarada como tipo[]

Ejemplos
float[] notas = new float[ALUMNOS];
int[] temperaturas = new int[7];

Matriz (array bidimensional):


matriz = new tipo[filas][columnas];

Ejemplo
int[][] temperaturas = new int[12][31];
Vectores y matrices - Java

-3-

Fernando Berzal

Uso
Para acceder a los elementos de un array,
utilizamos ndices
(para indicar la posicin del elemento dentro del array)

Vector (array unidimensional):


vector[ndice]

- En Java, el ndice de la primera componente


de un vector es siempre 0.
- El tamao del array puede obtenerse
utilizando la propiedad vector.length
- Por tanto, el ndice de la ltima componente es
vector.length-1

Ejemplo
float[] notas = new float[3];

Vectores y matrices - Java

-4-

Fernando Berzal

Matriz (array bidimensional):


matriz[ndice1][ndice2]

Una matriz, en realidad, es un vector de vectores:


- En Java, el ndice de la primera componente
de un vector es siempre 0, por lo que matriz[0][0]
ser el primer elemento de la matriz.
- El tamao del array puede obtenerse
utilizando la propiedad array.length:
matriz.length nos da el nmero de filas
matriz[0].length nos da el nmero de columnas
- Por tanto, el ltimo elemento de la matriz es
matriz[matriz.length-1][matriz[0].length-1]

Inicializacin en la declaracin
Podemos asignarle un valor inicial
a los elementos de un array en la propia declaracin
int vector[] = {1, 2, 3, 5, 7};
int matriz[][] = { {1,2,3}, {4,5,6} };

El compilador deduce automticamente las dimensiones del array.

Vectores y matrices - Java

-5-

Fernando Berzal

Manipulacin
de vectores y matrices
Las operaciones se realizan componente a componente

Ejemplo: Suma de los elementos de un vector


static float media (float datos[])
{
int
i;
int
n = datos.length;
float suma = 0;
for (i=0; i<n; i++)
suma = suma + datos[i];
return suma/n;
}

No es necesario utilizar todos los elementos de un vector, por lo que,


al trabajar con ellos, se puede utilizar una variable entera adicional que
nos indique el nmero de datos que realmente estamos utilizando:
El tamao del vector nos dice cunta memoria se ha reservado para
almacenar datos del mismo tipo, no cuntos datos del mismo tipo
tenemos realmente en el vector.
Ejemplo: Suma de los n primeros elementos de un vector
static float media (float datos[], int n)
{
int
i;
float suma = 0;
for (i=0; i<n; i++)
suma = suma + datos[i];
return suma/n;
}
Vectores y matrices - Java

-6-

Fernando Berzal

Ejemplo
public class Vectores
{
public static void main (String[] args)
{
int pares[] = { 2, 4, 6, 8, 10 };
int impares[] = { 1, 3, 5, 7, 9 };
mostrarVector(pares);
System.out.println("MEDIA="+media(pares));
mostrarVector(impares);
System.out.println("MEDIA="+media(impares));
}
static void mostrarVector (int datos[])
{
int
i;
for (i=0; i<datos.length; i++)
System.out.println(datos[i]);
}
static float media (int datos[])
{
int i;
int n = datos.length;
int suma = 0;
for (i=0; i<n; i++)
suma = suma + datos[i];
return suma/n;
}
}

Vectores y matrices - Java

-7-

Fernando Berzal

static int[] leerVector (int datos)


{
int
i;
int[] vector = new int[datos];
for (i=0; i<datos; i++)
vector[i] = leerValor();
return vector;
}

IMPORTANTE:
Cuando se pasa un array como parmetro,
se copia una referencia al array y no el conjunto de valores en s.
Por tanto, tenemos que tener cuidado con los efectos colaterales
que se producen si, dentro de un mdulo,
modificamos un vector que recibimos como parmetro.

Ejemplo
El siguiente mtodo lee los elementos de un vector ya creado
static void leerVector (int[] datos)
{
int
i;
for (i=0; i<datos.length; i++)
datos[i] = leerValor();
}

Vectores y matrices - Java

-8-

Fernando Berzal

Copia de arrays
La siguiente asignacin slo copia las referencias,
no crea un nuevo array:
int[] datos = pares;

Para copiar los elementos de un array,


hemos de crear un nuevo array y copiar los elementos uno a uno
int[] datos = new int[pares.length];
for (i=0; i<pares.length; i++)
datos[i] = pares[i]

Tambin podemos utilizar una funcin predefinida


en la biblioteca de clases estndar de Java:
System.arraycopy(from,fromIndex,to,toIndex,n);
int[] datos = new int[pares.length];
System.arraycopy(pares,0,datos,0,pares.length);

EXTRA:
La biblioteca de clases de Java incluye una clase auxiliar llamada
java.util.Arrays que incluye como mtodos algunas de las tareas
que se realizan ms a menudo con vectores:
- Arrays.sort(v) ordena los elementos del vector.
- Arrays.equals(v1,v2) comprueba si dos vectores son iguales.
- Arrays.fill(v,val) rellena el vector v con el valor val.
- Arrays.toString(v) devuelve una cadena que representa
el contenido del vector.
- Arrays.binarySearch(v, k) busca el valor k dentro del vector
v (que previamente ha de estar ordenado).
Vectores y matrices - Java

-9-

Fernando Berzal

Ejemplos
Un programa que muestra los parmetros
que le indicamos en la lnea de comandos:
public class Eco
{
public static void main(String args[])
{
int i;
for (i=0; i<args.length; i++)
System.out.println(args[i]);
}
}

Un mtodo que muestra el contenido de una matriz:


public static void mostrarMatriz (double matriz[][])
{
int i,j;
int filas = matriz.length;
int columnas = matriz[0].length;
// Recorrido de las filas de la matriz
for (i=0; i<filas; i++) {
// Recorrido de las celdas de una fila
for (j=0; j<columnas; j++) {
System.out.println ( matriz[+i+][+j+]=
+ matriz[i][j] );
}
}
}

Vectores y matrices - Java

- 10 -

Fernando Berzal

Algoritmos de ordenacin
Ordenacin por seleccin

static void ordenarSeleccion (double v[])


{
double tmp;
int i, j, pos_min;
int N = v.length;
for (i=0; i<N-1; i++) {
// Menor elemento del vector v[i..N-1]
pos_min = i;
for (j=i+1; j<N; j++)
if (v[j]<v[pos_min])
pos_min = j;
// Coloca el mnimo en v[i]
tmp = v[i];
v[i] = v[pos_min];
v[pos_min] = tmp; =
}
}

En cada iteracin, se selecciona el menor elemento del subvector no


ordenado y se intercambia con el primer elemento de este subvector.
Vectores y matrices - Java

- 11 -

Fernando Berzal

Ordenacin por insercin

static void ordenarInsercion (double v[])


{
double tmp;
int i, j;
int N = v.length;
for (i=1; i<N; i++) {
tmp = v[i];
for (j=i; (j>0) && (tmp<v[j-1]); j--)
v[j] = v[j-1];
v[j] = tmp;
}
}

En cada iteracin, se inserta un elemento del subvector no ordenado en


la posicin correcta dentro del subvector ordenado.
Vectores y matrices - Java

- 12 -

Fernando Berzal

Ordenacin por intercambio directo (mtodo de la burbuja)

static void ordenarBurbuja (double v[])


{
double tmp;
int i, j;
int N = v.length;
for (i=1; i<N; i++)
for (j=N-1; j>=i; j--)
if (v[j] < v[j-1]) {
tmp = v[j];
v[j] = v[j-1];
v[j-1] = tmp;
}
}

Estado del vector


tras cada iteracin:

En cada iteracin

Vectores y matrices - Java

- 13 -

Fernando Berzal

Ordenacin rpida (QuickSort)


1. Se toma un elemento arbitrario del vector, al que
denominaremos pivote (p).
2. Se divide el vector de tal forma que todos los elementos a la
izquierda del pivote sean menores que l, mientras que los que
quedan a la derecha son mayores que l.
3. Ordenamos, por separado, las dos zonas delimitadas por el
pivote.

static void quicksort


(double v[], int izda, int dcha)
{
int pivote; // Posicin del pivote
if (izda<dcha) {
pivote = partir (v, izda, dcha);
quicksort (v, izda, pivote-1);
quicksort (v, pivote+1, dcha);
}
}

Uso:
quicksort (vector, 0, vector.length-1);

Vectores y matrices - Java

- 14 -

Fernando Berzal

Obtencin del pivote

Mientras queden elementos mal colocados respecto al pivote:


a. Se recorre el vector, de izquierda a derecha, hasta
encontrar un elemento situado en una posicin i tal que
v[i] > p.
b. Se recorre el vector, de derecha a izquierda, hasta
encontrar otro elemento situado en una posicin j tal que
v[j] < p.
c. Se intercambian los elementos situados en las casillas i y
j (de modo que, ahora, v[i] < p < v[j]).

Vectores y matrices - Java

- 15 -

Fernando Berzal

/**
* Divisin del vector en dos partes
* @see quicksort
*
* @param primero ndice del primer elemento
* @param ultimo ndice del ltimo elemento
* @return Posicin del pivote
*
* @pre (primero>=0)
*
&& (primero<=ultimo)
*
&& (ultimo<v.length)
*/
private static int partir
(double v[], int primero, int ultimo)
{
double pivote = v[primero]; // Valor del pivote
double temporal;
// Variable auxiliar
int izda = primero+1;
int dcha = ultimo;
do {

// Pivotear

while ((izda<=dcha) && (v[izda]<=pivote))


izda++;
while ((izda<=dcha) && (v[dcha]>pivote))
dcha--;
if (izda < dcha) {
temporal = v[izda];
v[izda] = v[dcha];
v[dcha] = temporal;
dcha--;
izda++;
}
} while (izda <= dcha);
// Colocar el pivote en su sitio
temporal = v[primero];
v[primero] = v[dcha];
v[dcha] = temporal;
return dcha; // Posicin del pivote
}
Vectores y matrices - Java

- 16 -

Fernando Berzal

Algoritmos de bsqueda
Bsqueda lineal = Bsqueda secuencial
// Bsqueda lineal de un elemento en un vector
// - Devuelve la posicin de dato en el vector
// - Si dato no est en el vector, devuelve -1
static int buscar (double vector[], double dato)
{
int i;
int N = vector.length;
int pos = -1;
for (i=0; i<N; i++)
if (vector[i]==dato)
pos = i;
return pos;
}

Versin mejorada
// Bsqueda lineal de un elemento en un vector
// - Devuelve la posicin de dato en el vector
// - Si dato no est en el vector, devuelve -1
static int buscar (double vector[], double dato)
{
int i;
int N = vector.length;
int pos = -1;
for (i=0; (i<N) && (pos==-1); i++)
if (vector[i]==dato)
pos = i;
return pos;
}
Vectores y matrices - Java

- 17 -

Fernando Berzal

Bsqueda binaria
Precondicin
El vector ha de estar ordenado
Algoritmo
Se compara el dato buscado
con el elemento en el centro del vector:
- Si coinciden, hemos encontrado el dato buscado.
- Si el dato es mayor que el elemento central del vector,
tenemos que buscar el dato en segunda mitad del vector.
- Si el dato es menor que el elemento central del vector,
tenemos que buscar el dato en la primera mitad del
vector.

Vectores y matrices - Java

- 18 -

Fernando Berzal

// Bsqueda binaria de un elemento en un vector


// - Devuelve la posicin de dato en el vector
// - Si dato no est en el vector, devuelve -1
// Implementacin recursiva
// Uso: binSearch(vector,0,vector.length-1,dato)
static int binSearch
(double v[], int izq, int der, double buscado)
{
int centro = (izq+der)/2;
if (izq>der)
return -1;
else if (buscado==v[centro])
return centro;
else if (buscado<v[centro])
return binSearch(v, izq, centro-1, buscado);
else
return binSearch(v, centro+1, der, buscado);
}
// Implementacin iterativa
// Uso: binSearch (vector, dato)
static int binSearch (double v[], double buscado)
{
int izq = 0;
int der = v.length-1;
int centro = (izq+der)/2;
while ((izq<=der) && (v[centro]!=buscado)) {
if (buscado<v[centro])
der = centro 1;
else
izq = centro + 1;
centro = (izq+der)/2;
}
if (izq>der)
return -1;
else
return centro;
}
Vectores y matrices - Java

- 19 -

Fernando Berzal

Apndice:
Cadenas de caracteres
Una cadena de caracteres no es ms que un vector de caracteres.

La clase java.lang.String,
que se emplea para representar cadenas de caracteres en Java,
incluye distintos mtodos que nos facilitan algunas de las
operaciones que se suelen realizar con cadenas de caracteres:
- El mtodo substring nos permite obtener una subcadena:
String java=Java;
String s = java.substring(0,3);
System.out.println(s);

// Jav

- El mtodo charAt(n) nos devuelve el carcter que se


encuentra en la posicin n de la cadena:
String java=Java;
char c = java.atChar(2);
System.out.println(c);

// v

- El mtodo indexOf(s) nos devuelve la posicin de una


subcadena dentro de la cadena:
String java=Java;
int p = java.indexOf(av);
System.out.println(p);

// 1

- El mtodo replace(old,new) reemplaza subcadenas:


String java=Java;
java.replace(ava,ini);
System.out.println(java);
Vectores y matrices - Java

- 20 -

// Jini
Fernando Berzal

- El mtodo equals(s) se usa para comprobar si dos cadenas


son iguales:
if (s.equals(Hola)) {

RECORDATORIO:

el operador == no debe utilizarse


para comparar objetos.

- El mtodo startsWith(s) nos dice si una cadena empieza


con un prefijo determinado:
if (s.startsWith(get)) {

- El mtodo endsWith(s) nos dice si una cadena termina


con un sufijo determinado:
if (s.endsWith(.html)) {

- El mtodo length() devuelve la longitud de la cadena.

La clase java.lang.String incluye decenas de mtodos.

La lista completa de mtodos y los detalles de utilizacin de cada


mtodo se pueden consultar en la ayuda del JDK.

Vectores y matrices - Java

- 21 -

Fernando Berzal

Vectores y matrices
Relacin de ejercicios
1. Dado un vector de nmeros reales:
a. Escriba un mtodo max que nos devuelva el mximo de los valores
incluidos en el vector.
b. Escriba un mtodo min que nos devuelva el mnimo de los valores
incluidos en el vector.
c. Escriba un mtodo media que nos devuelva la media de los valores
incluidos en el vector.
d. Escriba un mtodo varianza que nos devuelva la varianza de los
valores incluidos en el vector.
e. Escriba un mtodo mediana que nos devuelva la mediana de los valores
incluidos en el vector.
f. Escriba un mtodo moda que nos devuelva la moda de los valores
incluidos en el vector
g. Escriba un mtodo percentil(n) que nos delvuelva el valor
correspondiente al percentil n en el conjunto de valores del vector.
2. Implemente una clase en Java, llamada Serie, que encapsule un vector de
nmeros reales e incluya mtodos (no estticos) que nos permitan calcular todos
los valores mencionados en el ejercicio anterior a partir de los datos
encapsulados por un objeto de tipo Serie.
3. Dado un vector de nmeros reales, escriba un mtodo que nos devuelva el
mximo y el mnimo de los valores incluidos en el vector.
4. Dado un vector, implemente un mtodo que inserte un elemento en una posicin
dada del vector.
NOTA: Insertar un elemento en el vector desplaza una posicin hacia la
derecha a los elementos del vector que han de quedar detrs del elemento
insertado. Adems, la insercin ocasiona la desaparicin del ltimo
elemento del vector.

5. Implemente un mtodo llamado secuencia que realice la bsqueda de la


secuencia en orden creciente ms larga dentro de un vector de enteros. El
mtodo ha de devolver tanto la posicin de la primera componente de la
secuencia como el tamao de la misma.
6. Una cadena de ADN se representa como una secuencia circular de bases
(adenina, timina, citosina y guanina) que es nica para cada ser vivo, por
ejemplo:
A
T
G
T
C
A
T
G
Dicha cadena se puede representar como un vector de caracteres recorrindola
en sentido horario desde la parte superior izquierda:
A

Se pide disear una clase que represente una secuencia de ADN e incluya un
mtodo booleano que nos devuelva true si dos cadenas de ADN coinciden.
MUY IMPORTANTE: La secuencia de ADN es cclica, por lo que puede comenzar
en cualquier posicin. Por ejemplo, las dos secuencias siguientes coinciden:
A

7. Dado un vector de nmeros reales, escriba un mtodo que ordene los elementos
del vector de mayor a menor.
8. Dado un vector de nmeros reales, escriba un mtodo que ordene los elementos
del vector de tal forma que los nmeros pares aparezcan antes que los nmeros
impares. Adems, los nmeros pares debern estar ordenados de forma
ascendente, mientras que los nmeros impares debern estar ordenados de forma
descendente. Esto es, el vector {1,2,3,4,5,6} quedar como {2,4,6,5,3,1}.
9. Crear una clase Matriz para manipular matrices que encapsule un array
bidimensional de nmeros reales.
a. Incluya en la clase mtodos que nos permitan acceder y modificar de
forma segura los elementos de la matriz (esto es, las variables de
instancia deben ser privadas y los mtodos han de comprobar la validez
de sus parmetros).
b. Escriba un mtodo que nos permita sumar matrices.
c. Implemente un mtodo que nos permita multiplicar matrices.
d. Cree un mtodo con el que se obtenga la traspuesta de una matriz.

10. En Java, para generar nmeros pseudoaleatorios, se puede utilizar la funcin


Math.random() definida en la clase java.lang.Math. Dicha funcin genera
una secuencia de nmeros pseudoaleatorios que se supone sigue una distribucin
uniforme (esto es, todos los valores aparecern con la misma probabilidad).
Escriba un programa que compruebe si el generador de nmeros
pseudoaleatorios de Java genera realmente nmeros aleatorios con una
distribucin uniforme.
Sugerencia: Genere un gran nmero de nmeros aleatorios (entre 0 y
100, por ejemplo) y compruebe que la distribucin resultante del nmero
de veces que aparece cada nmero es (ms o menos) uniforme. Por
ejemplo, mida la dispersin de la distribucin resultante utilizando una
medida como la varianza (y reutilice la clase Serie del ejercicio 2).
11. Realizar una simulacin de Monte Carlo para aproximar el valor del rea bajo
una curva f(x), en x [a, b].
Algoritmo: Generar puntos aleatorios en el rectngulo de extremos
(a, 0) y (b, m), con m = mxaxb f(x), y contar el nmero de puntos
que caen por debajo de la curva.
NOTA: Este mtodo permite generar nmeros
pseudoaleatorios que sigan cualquier distribucin
que nosotros deseemos. Por ejemplo, probar con
una distribucin normal.

12. Crear un programa modular para jugar a las 7 y media. Se trata de un juego de
cartas (con baraja espaola) en el que el objetivo es alcanzar una puntuacin de
7.5. Cada carta del 1 al 7 tiene su valor nominal y cada figura (sota, caballo y
rey) vale 0.5 puntos.
NOTA: Para barajar, mezcle los elementos de
un vector de cartas intercambiando en repetidas
ocasiones cartas elegidas al azar con la ayuda de
la funcin Math.random()

Recursividad
Preliminares
Uso de memoria en tiempo de ejecucin
Demostraciones por induccin
Concepto de recursividad
Utilidad
Funcionamiento de un algoritmo recursivo
Diseo de algoritmos recursivos
Recursividad frente a iteracin
Ejemplos
Sucesin de Fibonacci
Combinaciones
Las torres de Hanoi

Recursividad - Java

-0-

Fernando Berzal

Preliminares
Uso de memoria en tiempo de ejecucin
Al ejecutar una aplicacin Java,
la memoria usada por la aplicacin se divide en distintas zonas:

Memoria
Zona esttica

Programa

Variables de clase

Bytecodes

Pila

Heap
Objetos

Llamadas a mtodos

Programa
En una zona de memoria se cargan los bytecodes correspondientes a
las clases que forman parte de la aplicacin.
NOTA:

Para que se puedan encontrar los bytecodes


correspondientes a las distintas clases, los ficheros .class
deben estar en un directorio o en un fichero (.zip o .jar)
que figure en la variable de entorno CLASSPATH.

Zona esttica
Donde se almacenan las variables de clase (declaradas con static)
- Datos compartidos (datos globales).
- Datos que han de mantenerse ms all de la duracin de la
invocacin a un mtodo o de la vida de un objeto.
Recursividad - Java

-1-

Fernando Berzal

Pila
Donde se almacenan las variables locales (y parmetros) de los
mtodos que se invocan.
- Cada llamada a un mtodo provoca que se reserve espacio en la
pila para almacenar sus variables locales (y los valores de sus
parmetros).
- Al finalizar la ejecucin del mtodo, se libera el espacio ocupado
en la pila por las variables locales del mtodo.
Esta zona de memoria se denomina pila
por la forma en que evoluciona su estado:

Heap
Donde se almacena el estado de los objetos creados con new.
Java incluye un recolector de basura (garbage collector) que
libera la memoria ocupada por un objeto cuando ste deja de
usarse sin que nosotros tengamos que estar pendientes de liberar
la memoria que dejamos de utilizar.
Recursividad - Java

-2-

Fernando Berzal

Induccin
Una estrategia matemtica de demostracin.
Ejemplo
Sea S:intint una funcin
que nos da la suma de los n primeros nmeros naturales
De forma iterativa, podemos escribir
S(n) = 1 + 2 + 3 + + n
La expresin anterior es equivalente a

S ' ( n) =

n(n + 1)
2

Cmo demostramos que, para cualquier valor de n,


la expresin anterior es correcta?
1.

Vemos que, para n=1,


la expresin anterior es vlida: S(1) = 1 = S(1)

2.

Suponemos que la expresin funciona bien para n=k


y comprobamos si tambin es vlida para n=k+1

k ( k + 1)
k 2 + 3k + 2 ( k + 1)( k + 2)
S ( k + 1) = S ( k ) + ( k + 1) =
+ ( k + 1) =
=
= S ' ( k + 1)
2
2
2

Por tanto, por induccin, S(n)=S(n) para todo n1


Para realizar la demostracin, escribimos el trmino S(k+1)
en funcin del trmino anterior S(k) de forma recursiva.
Para poder utilizar esta definicin recursiva de la funcin,
lo nico que necesitamos es un caso base (en este caso, S(1)=1)
Cmo se evala una funcin recursiva?
S(4) = S(3) + 4 = (S(2) + 3) + 4 = ((S(1) + 2) + 3) + 4
= (((1) + 2) + 3) + 4 = ((3) + 3) + 4 = (6) + 4 = 10
Recursividad - Java

-3-

Fernando Berzal

Recursividad
Una funcin que se llama a s misma se denomina recursiva

Definicin recursiva: Vase definicin recursiva.


[FOLDOC: Free On-line Dictionary of Computing]

Utilidad
Cuando la solucin de un problema se puede expresar en
trminos de la resolucin de un problema de la misma naturaleza,
aunque de menor complejidad.
Divide y vencers:
Un problema complejo se divide en otros problemas ms sencillos
(del mismo tipo)
Slo tenemos que conocer la solucin no recursiva para algn
caso sencillo (denominado caso base) y hacer que la divisin de
nuestro problema acabe recurriendo a los casos base que hayamos
definido.
Como en las demostraciones por induccin, podemos considerar
que tenemos resuelto el problema ms simple para resolver el
problema ms complejo (sin tener que definir la secuencia exacta de
pasos necesarios para resolver el problema).
Recursividad - Java

-4-

Fernando Berzal

Ejemplo
Cuntas formas hay de colocar n objetos en orden?
- Podemos colocar cualquiera de los n objetos en la primera
posicin.
- A continuacin, colocamos los (n-1) objetos restantes.
- Por tanto: P(n) = n P(n-1) = n!

Factorial calculado de forma recursiva:


static int factorial (int n)
{
int resultado;
if (n==0)
// Caso base
resultado = 1;
else
// Caso general
resultado = n*factorial(n-1);
return resultado;
}
fact(0)

fact(3)
fact(4) n = 3
n=4

n=4

fact(1)

n=0

fact(2)

n=1

n=1

n=2

n=2

1
1
n=1

2
n=2

n=2

n=2

6
n=3

n=3

n=3

n=3

n=3

n=3

n=4

n=4

n=4

n=4

n=4

n=4

24
n=4

tiempo
Recursividad - Java

-5-

Fernando Berzal

Funcionamiento de un algoritmo recursivo


- Se descompone el problema en problemas de menor complejidad
(algunos de ellos de la misma naturaleza que el problema original).
- Se resuelve el problema para, al menos, un caso base.
- Se compone la solucin final a partir de las soluciones parciales que
se van obteniendo.

Ejemplo
static int potencia (int x, int n)
{
if (n==0)
// Caso base
return 1;
else
// Caso general
return x * potencia(x,n-1);
}

n=0
x=5

n=1

n=1

n=1

x=5

x=5

x=5

n=2

n=2

n=2

n=2

n=2

x=5

x=5

x=5

x=5

x=5

25

n=3

n=3

n=3

n=3

n=3

n=3

n=3

x=5

x=5

x=5

x=5

x=5

x=5

x=5

125

Clculo de 53

Recursividad - Java

-6-

Fernando Berzal

Diseo de algoritmos recursivos


1. Resolucin de problema para los casos base:
o Sin emplear recursividad.
o Siempre debe existir algn caso base.

2. Solucin para el caso general:


o Expresin de forma recursiva.
o Pueden incluirse pasos adicionales
(para combinar las soluciones parciales).

Siempre se debe avanzar hacia un caso base:


Las llamadas recursivas simplifican el problema y, en ltima instancia,
los casos base nos sirven para obtener la solucin.

- Los casos base


corresponden a situaciones que se pueden resolver con facilidad.
- Los dems casos se resuelven
recurriendo, antes o despus, a alguno(s) de los casos base.

De esta forma, podemos resolver problemas complejos


que seran muy difciles de resolver directamente.

Recursividad - Java

-7-

Fernando Berzal

Recursividad vs. iteracin


Aspectos que hay que considerar
al decidir cmo implementar la solucin a un problema
(de forma iterativa o de forma recursiva):
- La carga computacional
(tiempo de CPU y espacio en memoria)
asociada a las llamadas recursivas.
- La redundancia
(algunas soluciones recursivas
resuelven el mismo problema en repetidas ocasiones).
- La complejidad de la solucin
(en ocasiones, la solucin iterativa es muy difcil de encontrar).
- La concisin, legibilidad y elegancia del cdigo resultante
(la solucin recursiva del problema puede ser ms sencilla).
Ejemplo: Versin mejorada del clculo de xn
static int potencia (int x, int n)
{
int aux;
if (n==0) {
return 1;
} else {
aux = potencia(x, n/2);
if (n%2 == 0)
return aux * aux;
else
return x * aux * aux;
}
}
Recursividad - Java

-8-

Fernando Berzal

Ejemplo: Sucesin de Fibonacci

Solucin recursiva
static int fibonacci (int n)
{
if ((n == 0) || (n == 1))
return 1;
else
return fibonacci(n-1) + fibonacci(n-2);
}
Solucin iterativa
static int fibonacci (int n)
{
int actual, ant1, ant2;
ant1 = ant2 = 1;
if ((n == 0) || (n == 1)) {
actual = 1;
} else
for (i=2; i<=n; i++) {
actual = ant1 + ant2;
ant2 = ant1;
ant1 = actual;
}
}
return actual;
}
Clculo recursivo de fibonacci(5)
Recursividad - Java

-9-

Fernando Berzal

Ejemplo: Combinaciones
De cuntas formas se pueden seleccionar
m elementos de un conjunto de n?
Si cogemos dos letras del conjunto {A,B,C,D,E}
podemos obtener 10 parejas diferentes:
{A, B}

{A, C}
{B, C}

{A, D}
{B, D}
{C, D}

{A, E}
{B, E}
{C, E}
{D, E}

n n 1 n 1
=
+

m m m 1

n
0 1 2 3 4 5
0
1
2
3
4
5
m
0 C0 C0 C0 C0 C0 C0
1 C 2C 3 C 4 C 5 C
1
1
1
1
1
1
2

2C 3 C 4 C 5 C
2
2
2
2

3 C 4 C 5 C 6C
3
3
3
3

4C 5C
4
4

Recursividad - Java

- 10 -

Fernando Berzal

Implementacin recursiva:
static int combinaciones (int n, int m)
{
if ((m == 0) || (m == n))
return 1;
else
return combinaciones(n-1, m)
+ combinaciones(n-1, m-1);
}

El algoritmo recursivo anterior es muy ineficiente


porque realiza muchas veces los mismos clculos.
n

De hecho, se realizan llamadas recursivas.


m

Para mejorar la eficiencia del algoritmo recursivo


podemos buscar un algoritmo iterativo equivalente:
- Usando una matriz en la que iremos almacenando los valores que
vayamos calculando para no repetir dos veces el mismo trabajo.
n

n!

- Aplicando directamente la expresin =


m m!(n m)!

Recursividad - Java

- 11 -

Fernando Berzal

Ejemplo: Las torres de Hanoi

Mover n discos del poste 1 al poste 3


(utilizando el poste 2 como auxiliar):
hanoi (n, 1, 2, 3);

Solucin recursiva:
static void hanoi
(int n, int inic, int tmp, int fin)
{
if (n > 0) {
// Mover n-1 discos de "inic" a "tmp".
// El temporal es "fin".
hanoi (n-1, inic, fin, tmp);
// Mover el que queda en "inic" a "fin"
System.out.println(inic+->+fin);
// Mover n-1 discos de "tmp" a "fin".
// El temporal es "inic".
hanoi (n-1, tmp, inic, fin);
}
}
Recursividad - Java

- 12 -

Fernando Berzal

Solucin para 3 discos

Segn la leyenda, los monjes de un templo tenan que mover una pila
de 64 discos sagrados de un sitio a otro. Slo podan mover un disco al
da y, en el templo, slo haba otro sitio en el que podan dejarlos,
siempre ordenados de forma que los mayores quedasen en la base.
El da en que los monjes realizasen el ltimo movimiento,
el final del mundo habra llegado en cuntos das?
Recursividad - Java

- 13 -

Fernando Berzal

Recursividad
Relacin de ejercicios
1. Demuestre por induccin que la funcin Q(n)=12+22+32++n2
puede expresarse como Q(n) = n (n+1) (2n+1) / 6
2. Demuestre por induccin que, para todo n mayor o igual que 1,
133 divide a 11n+1 + 122n-1
3. Demuestre por induccin que, para todo n mayor o igual que 4, n!>2n
4. Dado un tablero de ajedrez (de tamao 8x8) al que le falta una casilla, podemos
rellenar las dems casillas utilizando nicamente teselas con forma de L?

PISTA: Realice una demostracin por induccin


- Cuntas casillas faltan por rellenar?
- Cuntas teselas se han colocado ya?
- Cuntas casillas quedan tras colocar otra tesela?
Generalice la demostracin para un tablero de tamao 2nx2n
5. Demuestre que, con sellos de 4 y 5 cntimos, se puede franquear cualquier carta
que requiera sellos por valor de 12 o ms cntimos.
6. Un granjero ha comprado una pareja de conejos para criarlos y luego venderlos.
Si la pareja de conejos produce una nueva pareja cada mes y la nueva pareja
tarda un mes ms en ser tambin productiva, cuntos pares de conejos podr
poner a la venta el granjero al cabo de un ao?
FUENTE: Liber abaci, seccin III

7. Dado el siguiente fragmento de cdigo:

static final double N = 2;


static final double PREC = 1e-6;
static double f (double x)
{
return x*x-N;
}
static double bisect (double min, double max)
{
double med = (min+max)/2;
if (max-min<PREC) {
return med;
} else if (f(min)*f(med)<0) {
return bisect (min,med);
} else {
return bisect (med,max);
}
}

a) Qu calcula la llamada a la funcin recursiva bisect(0,N)? Si cambiamos el


valor de N, qu estaramos calculando? Y si cambisemos la funcin f(x)?
b) Implemente un algoritmo iterativo equivalente.

8. Dado el siguiente algoritmo recursivo:

void f(int num, int div)


{
if (num>1) {
if ((num%div) == 0) {
System.out.println(div);
f(num/div,div);
} else {
f(num,div+1);
}
}
}

a) Dado un nmero cualquiera x, qu nos muestra por pantalla la llamada a la funcin


recursiva f(x,2)? Cul sera un nombre ms adecuado para la funcin f?
b) Implemente un algoritmo iterativo equivalente.

9. Cul es el resultado de esta funcin para distintos valores de x?

static int f (int x)


{
if (x > 100)
return (x - 10);
else
return (f (f (x+11)));
}

10. Construya una funcin que convierta un nmero decimal en una cadena que represente
el valor del nmero en hexadecimal (base 16). A continuacin, generalice la funcin
para convertir un nmero decimal en un nmero en base B (con B<10).

Recordatorio: El cambio de base se realiza mediante divisiones sucesivas por 16


en las cuales los restos determinan los dgitos hexadecimales del nmero segn
la siguiente correspondencia:
Resto
Dgito

0
0

1
1

2
2

3
3

4
4

5
5

6
6

7
7

8
8

9
9

10 11 12 13 14 15
A B C D E F

Por ejemplo:

65029|10 = FE05|16
11. Implemente, tanto de forma recursiva como de forma iterativa, una funcin que nos
diga si una cadena de caracteres es simtrica (un palndromo). Por ejemplo,
DABALEARROZALAZORRAELABAD es un palndromo.

12. Implemente, tanto de forma recursiva como de forma iterativa, una funcin que le d la
vuelta a una cadena de caracteres.
NOTA:
Obviamente, si la cadena es un palndromo, la cadena y su inversa coincidirn.
13. Implemente, tanto de forma recursiva como de forma iterativa, una funcin que
permitan calcular el nmero de combinaciones de n elementos tomados de m en m.
Realice dos versiones de la implementacin iterativa, una aplicando la frmula y otra
utilizando una matriz auxiliar (en la que se vaya construyendo el tringulo de Pascal).

14. Implemente, tanto de forma recursiva como de forma iterativa, una funcin que nos
devuelva el mximo comn divisor de dos nmeros enteros utilizando el algoritmo de
Euclides.
ALGORITMO DE EUCLIDES
Dados dos nmeros enteros positivos m y n, tal que m > n,
para encontrar su mximo comn divisor
(es decir, el mayor entero positivo que divide a ambos):
- Dividir m por n para obtener el resto r (0 r < n)
- Si r = 0, el MCD es n.
- Si no, el mximo comn divisor es MCD(n,r).

15. La ordenacin por mezcla (mergesort) es un mtodo de ordenacin que se basa en un


principio muy simple: se ordenan las dos mitades de un vector y, una vez ordenadas, se
mezclan. Escriba un programa que implemente este mtodo de ordenacin.

16. Disee e implemente un algoritmo que imprima todas las posibles descomposiciones de
un nmero natural como suma de nmeros menores que l (sumas con ms de un
sumando).

17. Disee e implemente un mtodo recursivo que nos permita obtener el determinante de
una matriz cuadrada de dimensin n.

18. Disee e implemente un programa que juegue al juego de cifras de Cifras y Letras.
El juego consiste en obtener, a partir de 6 nmeros, un nmero lo ms cercano posible a
un nmero de tres cifras realizando operaciones aritmticas con los 6 nmeros.

19. Problema de las 8 reinas: Se trata de buscar la forma de colocar 8 reinas en un tablero
de ajedrez de forma que ninguna de ellas amenace ni se vea amenazada por otra reina.
Algoritmo:
- Colocar la reina i en la primera casilla vlida de la fila i
- Si una reina no puede llegar a colocarse en ninguna casilla, se vuelve
atrs y se cambia la posicin de la reina i-1
- Intentar colocar las reinas restantes en las filas que quedan

20. Salida de un laberinto: Se trata de encontrar un camino que nos permita salir de un
laberinto definido en una matriz NxN. Para movernos por el laberinto, slo podemos
pasar de una casilla a otra que sea adyacente a la primera y no est marcada como una
casilla prohibida (esto es, las casillas prohibidas determinan las paredes que forman el
laberinto).
Algoritmo:
- Se comienza en la casilla (0,0) y se termina en la casilla (N-1,N-1)
- Nos movemos a una celda adyacente si esto es posible.
- Cuando llegamos a una situacin en la que no podemos realizar ningn
movimiento que nos lleve a una celda que no hayamos visitado ya,
retrocedemos sobre nuestros pasos y buscamos un camino alternativo.

Tcnicas tiles
en el desarrollo de software
Refactorizacin
Ejemplo: Generacin de nmeros primos
Cundo hay que refactorizar?
Algunas refactorizaciones comunes
Pruebas de unidad
JUNIT
Ejemplo: La clase Money
TDD [Test-Driven Development]
Caso prctico: Bolera

Bibliografa
Robert C. Martin:
Agile Software Development: Principles, Patterns, and Practices.
Prentice Hall, 2003. ISBN 0-13-597444-5.
Martin Fowler:
Refactoring: Improving the design of existing code.
Addison-Wesley, 2000. ISBN 0-201-48567-2.
Kent Beck:
Test-Driven Development by Example.
Addison-Wesley, 2003. ISBN 0-321-14653-0

Refactorizacin
Definicin
Refactorizacin (n)
Cambio realizado a la estructura interna del software
para hacerlo ms fcil de comprender
y
ms fcil de modificar
sin cambiar su comportamiento observable.
Refactorizar (v)
Reestructurar el software
aplicando una secuencia de refactorizaciones.

Por qu se refactoriza el software?


1.

Para mejorar su diseo


a. Conforme se modifica, el software pierde su estructura.
b. Eliminar cdigo duplicado simplificar su mantenimiento.

2. Para hacerlo ms fcil de entender


p.ej. La legibilidad del cdigo facilita su mantenimiento
3. Para encontrar errores
p.ej. Al reorganizar un programa, se pueden apreciar con mayor
facilidad las suposiciones que hayamos podido hacer.
4. Para programar ms rpido
Al mejorar el diseo del cdigo, mejorar su legibilidad
y reducir los errores que se cometen al programar,
se mejora la productividad de los programadores.
Tcnicas tiles en el desarrollo de software

-1-

Fernando Berzal

Ejemplo
Generacin de nmeros primos
Robert C. Martin, The Craftsman column,
Software Development magazine, julio-septiembre 2002
Para conseguir un trabajo nos plantean el siguiente problema
Implementar una clase que sirva para calcular todos los nmeros
primos de 1 a N utilizando la criba de Eratstenes
Una primera solucin
Necesitamos crear un mtodo que reciba como parmetro un valor
mximo y devuelva como resultado un vector con los nmeros primos.
Para intentar lucirnos, escribimos
/**
* Clase para generar todos los nmeros primos de 1 hasta
* un nmero mximo especificado por el usuario. Como
* algoritmo se utiliza la criba de Eratstenes.
* <p>
* Eratstenes de Cirene (276 a.C., Cirene, Libia 194
* a.C., Alejandra, Egipto) fue el primer hombre que
* calcul la circunferencia de la Tierra. Tambin
* se le conoce por su trabajo con calendarios que ya
* incluan aos bisiestos y por dirigir la mtica
* biblioteca de Alejandra.
* <p>
* El algoritmo es bastante simple: Dado un vector de
* enteros empezando en 2, se tachan todos los mltiplos
* de 2. A continuacin, se encuentra el siguiente
* entero no tachado y se tachan todos sus mltiplos. El
* proceso se repite hasta que se pasa de la raz cuadrada
* del valor mximo. Todos los nmeros que queden sin
* tachar son nmeros primos.
*
* @author Fernando Berzal
* @version 1.0 Enero2005 (FB)
*/

Tcnicas tiles en el desarrollo de software

-2-

Fernando Berzal

El cdigo lo escribimos todo en un nico (y extenso) mtodo, que


procuramos comentar correctamente:
public class Criba
{
/**
* Generar nmeros primos de 1 a max
* @param max es el valor mximo
* @return Vector de nmeros primos
*/
public static int[] generarPrimos (int max)
{
int i,j;
if (max >= 2) {
// Declaraciones
int dim = max + 1; // Tamao del array
boolean[] esPrimo = new boolean[dim];
// Inicializar el array
for (i=0; i<dim; i++)
esPrimo[i] = true;
// Eliminar el 0 y el 1, que no son primos
esPrimo[0] = esPrimo[1] = false;
// Criba
for (i=2; i<Math.sqrt(dim)+1; i++) {
if (esPrimo[i]) {
// Eliminar los mltiplos de i
for (j=2*i; j<dim; j+=i)
esPrimo[j] = false;
}
}
// Cuntos primos hay?
int cuenta = 0;
for (i=0; i<dim; i++) {
if (esPrimo[i])
cuenta++;
}
Tcnicas tiles en el desarrollo de software

-3-

Fernando Berzal

// Rellenar el vector de nmeros primos


int[] primos = new int[cuenta];
for (i=0, j=0; i<dim; i++) {
if (esPrimo[i])
primos[j++] = i;
}
return primos;
} else { // max < 2
return new int[0];

// Vector vaco

}
}
}

Para comprobar que nuestro cdigo funciona bien, decidimos probarlo


con un programa que incluye distintos casos de prueba (para lo que
usaremos la herramienta JUnit, disponible en http://www.junit.org/):
import junit.framework.*;
import java.util.*;

// JUnit

// Clase con casos de prueba para Criba


public class CribaTest extends TestCase
{
// Programa principal (usa un componente de JUnit)
public static void main(String args[])
{
junit.swingui.TestRunner.main (
new String[] {"CribaTest"});
}
// Constructor
public CribaTest (String nombre)
{
super(nombre);
}
Tcnicas tiles en el desarrollo de software

-4-

Fernando Berzal

// Casos de prueba
public void testPrimos()
{
int[] nullArray = Criba.generarPrimos(0);
assertEquals(nullArray.length, 0);
int[] minArray = Criba.generarPrimos(2);
assertEquals(minArray.length, 1);
assertEquals(minArray[0], 2);
int[] threeArray = Criba.generarPrimos(3);
assertEquals(threeArray.length, 2);
assertEquals(threeArray[0], 2);
assertEquals(threeArray[1], 3);
int[] centArray = Criba.generarPrimos(100);
assertEquals(centArray.length, 25);
assertEquals(centArray[24], 97);
}
}

Al ejecutar los casos de prueba, conseguimos tener ciertas garantas de


que el programa funciona correctamente:

Tcnicas tiles en el desarrollo de software

-5-

Fernando Berzal

Despus de eso, vamos orgullosos a ensear nuestro programa y


un programador no dice que, si queremos el trabajo, mejor no le
enseemos eso al jefe de proyecto (que no tiene demasiada paciencia)
Veamos qu cosas hemos de mejorar
Primeras mejoras
Parece evidente que nuestro mtodo generarPrimos realiza tres
funciones diferentes, por lo que de generarPrimos extraemos tres
mtodos diferentes. Adems, buscamos un nombre ms adecuado para
la clase y eliminamos todos los comentarios innecesarios.
/**
* Esta clase genera todos los nmeros primos de 1 hasta un
* nmero mximo especificado por el usuario utilizando la
* criba de Eratstenes
* <p>
* Dado un vector de enteros empezando en 2, se tachan todos
* los mltiplos de 2. A continuacin, se encuentra el
* siguiente entero no tachado y se tachan sus mltiplos.
* Cuando se llega a la raz cuadrada del valor mximo, los
* nmeros que queden sin tachar son los nmeros primos
*
* @author Fernando Berzal
* @version 2.0 Enero'2005 (FB)
*/

public class GeneradorDePrimos


{
private static int dim;
private static boolean esPrimo[];
private static int primos[];
public static int[] generarPrimos (int max)
{
if (max < 2) {
return new int[0]; // Vector vaco
} else {
inicializarCriba(max);
cribar();
rellenarPrimos();
return primos;
}
}
Tcnicas tiles en el desarrollo de software

-6-

Fernando Berzal

private static void inicializarCriba (int max)


{
int i;
dim = max + 1;
esPrimo = new boolean[dim];
for (i=0; i<dim; i++)
esPrimo[i] = true;
esPrimo[0] = esPrimo[1] = false;
}
private static void cribar ()
{
int i,j;
for (i=2; i<Math.sqrt(dim)+1; i++) {
if (esPrimo[i]) {
// Eliminar los mltiplos de i
for (j=2*i; j<dim; j+=i)
esPrimo[j] = false;
}
}
}
private static void rellenarPrimos ()
{
int i, j, cuenta;
// Contar primos
cuenta = 0;
for (i=0; i<dim; i++)
if (esPrimo[i])
cuenta++;
// Rellenar el vector de nmeros primos
primos = new int[cuenta];
for (i=0, j=0; i<dim; i++)
if (esPrimo[i])
primos[j++] = i;
}
}

Los mismos casos de prueba de antes nos permiten comprobar que,


tras la refactorizacin, el programa sigue funcionando correctamente.
Tcnicas tiles en el desarrollo de software

-7-

Fernando Berzal

Un segundo intento
El cdigo ha mejorado pero an es algo ms enrevesado de la cuenta:
eliminamos la variable dim (nos vale esPrimo.length),
elegimos identificadores ms adecuados para los mtodos y
reorganizamos el interior del mtodo inicializarCandidatos
(el antiguo inicializarCriba).
public class GeneradorDePrimos
{
private static boolean esPrimo[];
private static int primos[];
public static int[] generarPrimos (int max)
{
if (max < 2) {
return new int[0];
} else {
inicializarCandidatos(max);
eliminarMultiplos();
obtenerCandidatosNoEliminados();
return primos;
}
}
private static void inicializarCandidatos (int max)
{
int i;
esPrimo = new boolean[max+1];
esPrimo[0] = esPrimo[1] = false;
for (i=2; i<esPrimo.length; i++)
esPrimo[i] = true;
}
private static void eliminarMultiplos ()
// Cdigo del antiguo mtodo cribar()
private static void obtenerCandidatosNoEliminados ()
// Cdigo del antiguo mtodo rellenarPrimos()
}

El cdigo resulta ms fcil de leer tras la refactorizacin.


Tcnicas tiles en el desarrollo de software

-8-

Fernando Berzal

Mejoras adicionales
El bucle anidado de eliminarMultiplos poda eliminarse si usamos
un mtodo auxiliar para eliminar los mltiplos de un nmero concreto.
Por otro lado, la raz cuadrada que aparece en eliminarMultiplos
no queda muy claro de dnde proviene (en realidad, es el valor
mximo que puede tener el menor factor de un nmero no primo
menor o igual que N). Adems, el +1 resulta innecesario.
private static void eliminarMultiplos ()
{
int i;
for (i=2; i<maxFactor(); i++)
if (esPrimo[i])
eliminarMultiplosDe(i);
}
private static int maxFactor ()
{
return (int) Math.sqrt(esPrimo.length) + 1;
}
private static void eliminarMultiplosDe (int i)
{
int multiplo;
for ( multiplo=2*i;
multiplo<esPrimo.length;
multiplo+=i)
esPrimo[multiplo] = false;
}

De forma anloga, el mtodo obtenerCandidatosNoEliminados


tiene dos partes bien definidas, por lo que podemos extraer un mtodo
que se limite a contar el nmero de primos obtenidos
Hemos ido realizando cambios que mejoran la implementacin
sin modificar su comportamiento externo (su interfaz),
algo que verificamos tras cada refactorizacin
volviendo a ejecutar los casos de prueba.
Tcnicas tiles en el desarrollo de software

-9-

Fernando Berzal

Cundo hay que refactorizar?


Cuando se est escribiendo nuevo cdigo
Al aadir nueva funcionalidad a un programa (o modificar su
funcionalidad existente), puede resultar conveniente refactorizar:
- para que ste resulte ms fcil de entender, o
- para simplificar la implementacin de las nuevas funciones
cuando el diseo no estaba inicialmente pensado para lo que
ahora tenemos que hacer.
Cuando se intenta corregir un error
La mayor dificultad de la depuracin de programas radica en que
hemos de entender exactamente cmo funciona el programa para
encontrar el error. Cualquier refactorizacin que mejore la calidad del
cdigo tendr efectos positivos en la bsqueda del error.
De hecho, si el error se col en el cdigo es porque
no era lo suficientemente claro cuando lo escribimos.
Cuando se revisa el cdigo
Una de las actividades ms productivas desde el punto de vista de la
calidad del software es la realizacin de revisiones del cdigo
(recorridos e inspecciones). Llevada a su extremo, la programacin
siempre se realiza por parejas (pair programming, una de las tcnicas
de la programacin extrema, XP [eXtreme Programming]).

Por qu es importante la refactorizacin?


Cuando se corrige un error o se aade una nueva funcin, el valor
actual de un programa aumenta. Sin embargo, para que un programa
siga teniendo valor, debe ajustarse a nuevas necesidades (mantenerse),
que puede que no sepamos prever con antelacin. La refactorizacin,
precisamente, facilita la adaptacin del cdigo a nuevas necesidades.
Tcnicas tiles en el desarrollo de software - 10 -

Fernando Berzal

Qu sntomas indican que debera refactorizar?


El cdigo es ms difcil de entender (y, por tanto, de cambiar) cuando:
- usa identificadores mal escogidos,
- incluye fragmentos de cdigo duplicados,
- incluye lgica condicional compleja,
- los mtodos usan un nmero elevado de parmetros,
- incluye fragmentos de cdigo secuencial muy extensos,
- est dividido en mdulos enormes (estructura monoltica),
- los mdulos en los que se divide no resultan razonables desde el
punto de vista lgico (cohesin baja),
- los distintos mdulos de un sistema estn relacionados con otros
muchos mdulos de un sistema (acoplamiento fuerte),
- un mtodo accede continuamente a los datos de un objeto de una
clase diferente a la clase en la que est definida (posiblemente, el
mtodo debera pertenecer a la otra clase),
- una clase incluye variables de instancia que deberan ser
variables locales de alguno(s) de sus mtodos,
- mtodos que realizan funciones anlogas se usan de forma
diferente (tienen nombres distintos y/o reciben los parmetros en
distinto orden),
- un comentario se hace imprescindible para poder entender un
fragmento de cdigo (deberamos re-escribir el cdigo de forma
que podamos entender su significado).
NOTA: Esto no quiere decir que dejemos de comentar el cdigo.
Tcnicas tiles en el desarrollo de software - 11 -

Fernando Berzal

Algunas refactorizaciones comunes


Algunos IDEs (p.ej. Eclipse) permiten realizarlas de forma automtica.

Renombrar mtodo [rename method]


Cuando el nombre de un mtodo no refleja su propsito
1. Declarar un mtodo nuevo con el nuevo nombre.
2. Copiar el cuerpo del antiguo mtodo al nuevo mtodo
(y realizar cualquier modificacin que resulte necesaria).
3. Compilar
(para verificar que no hemos introducido errores sintcticos)
4. Reemplazar el cuerpo del antiguo mtodo por una llamada al
nuevo mtodo (este paso se puede omitir si no se hace referencia
al antiguo mtodo desde muchos lugares diferentes).
5. Compilar y probar.
6. Encontrar todas las referencias al antiguo mtodo y cambiarlas
por invocaciones al nuevo mtodo.
7. Eliminar el antiguo mtodo.
8. Compilar y probar.

NOTA:
Si el antiguo mtodo era un mtodo pblico usado por otros
componentes o aplicaciones y no podemos eliminarlo, el antiguo
mtodo se deja en su lugar (como una llamada al nuevo mtodo)
y se marca como deprecated con Javadoc (@deprecated).

Tcnicas tiles en el desarrollo de software - 12 -

Fernando Berzal

Extraer mtodo [extract method]


Convertir un fragmento de cdigo en un mtodo
cuyo identificador explique el propsito del fragmento de cdigo.
1. Crear un nuevo mtodo y buscarle un identificador adecuado.
2. Copiar el fragmento de cdigo en el cuerpo del mtodo.
3. Buscar en el cdigo extrado referencias a variables locales del
mtodo original (estas variables se convertirn en los
parmetros, variables locales y resultado del nuevo mtodo):
a. Si una variable se usa slo en el fragmento de cdigo
extrado, se declara en el nuevo mtodo como variable
local de ste.
b. Si el valor de una variable slo se lee en el fragmento de
cdigo extrado, la variable ser un parmetro del nuevo
mtodo.
c. Si una variable se modifica en el fragmento de cdigo
extrado, se intenta convertir el nuevo mtodo en una
funcin que da como resultado el valor que hay que
asignarle a la variable modificada.
d. Compilar el cdigo para comprobar que todas las
referencias a variables son vlidas
4. Reemplazar el fragmento de cdigo en el mtodo original por
una llamada al nuevo mtodo.
5. Eliminar las declaraciones del mtodo original correspondientes
a las variables que ahora son variables locales del nuevo mtodo.
6. Compilar y probar.

Tcnicas tiles en el desarrollo de software - 13 -

Fernando Berzal

Versin final
Como sabemos que no es muy recomendable usar demasiado a
menudo la palabra reservada static, con unos pequeos cambios
convertimos GeneradorDePrimos en una clase de la que se puedan
crear distintos objetos.
En primer lugar, modificamos los casos de prueba con los que
comprobaremos el funcionamiento de nuestro generador de primos:
import junit.framework.*;
public class GeneradorDePrimosTest extends TestCase
{
GeneradorDePrimos generador;
int[]
primos;
public static void main(String args[])
{
junit.swingui.TestRunner.main(
new String[] {"GeneradorDePrimosTest"});
}
public GeneradorDePrimosTest(String name)
{
super(name);
}
public void testPrimos0()
{
generador = new GeneradorDePrimos(0);
primos = generador.getPrimos();
assertEquals( primos.length, 0);
}
public void testPrimos2()
{
generador = new GeneradorDePrimos(2);
primos = generador.getPrimos();
assertEquals(primos.length, 1);
assertEquals(primos[0], 2);
}
Tcnicas tiles en el desarrollo de software - 10 -

Fernando Berzal

public void testPrimos3()


{
generador = new GeneradorDePrimos(3);
primos = generador.getPrimos();
assertEquals(primos.length, 2);
assertEquals(primos[0], 2);
assertEquals(primos[1], 3);
}
public void testPrimos100()
{
generador = new GeneradorDePrimos(100);
primos = generador.getPrimos();
assertEquals(primos.length, 25);
assertEquals(primos[24], 97);
}
}

A continuacin, creamos un constructor para GeneradorDePrimos


(que construye el vector de nmeros primos) y aadimos un mtodo
getPrimos() con el cual acceder a este vector desde el exterior
/**
* Esta clase genera todos los nmeros primos de 1
* hasta un nmero mximo especificado por el usuario
* utilizando la criba de Eratstenes.
* <p>
* Dado un vector de enteros empezando en 2, se tachan
* todos los mltiplos de 2. A continuacin, se
* encuentra el siguiente entero no tachado y se
* tachan sus mltiplos. Los nmeros que queden sin
* tachar al final son los nmeros primos entre 1 y N.
*
* @author Fernando Berzal
* @version 3.0 Enero'2005 (FB)
*/
public class GeneradorDePrimos
{
private boolean esPrimo[];
private int primos[];
Tcnicas tiles en el desarrollo de software - 11 -

Fernando Berzal

public GeneradorDePrimos (int max)


{
if (max < 2) {
primos = new int[0];

// Vector vaco

} else {
inicializarCandidatos(max);
eliminarMultiplos();
obtenerCandidatosNoEliminados();
}
}

public int[] getPrimos ()


{
return primos;
}

private void inicializarCandidatos (int max)


{
int i;
esPrimo = new boolean[max+1];
esPrimo[0] = esPrimo[1] = false;
for (i=2; i<esPrimo.length; i++)
esPrimo[i] = true;
}

private void eliminarMultiplos ()


{
int i;
for (i=2; i<maxFactorPrimo(); i++)
if (esPrimo[i])
eliminarMultiplosDe(i);
}

Tcnicas tiles en el desarrollo de software - 12 -

Fernando Berzal

private int maxFactorPrimo ()


{
return (int) Math.sqrt(esPrimo.length) + 1;
}

private void eliminarMultiplosDe (int i)


{
int multiplo;
for ( multiplo=2*i;
multiplo<esPrimo.length;
multiplo+=i )
esPrimo[multiplo] = false;
}

private void obtenerCandidatosNoEliminados ()


{
int i, j;
primos = new int[numPrimos()];
for (i=0, j=0; i<esPrimo.length; i++) {
if (esPrimo[i])
primos[j++] = i;
}
}

private int numPrimos ()


{
int i;
int cuenta = 0;
for (i=0; i<esPrimo.length; i++) {
if (esPrimo[i])
cuenta++;
}
return cuenta;
}
}
Tcnicas tiles en el desarrollo de software - 13 -

Fernando Berzal

Pruebas de unidad
con JUnit
Cuando se implementa software, resulta recomendable comprobar
que el cdigo que hemos escrito funciona correctamente.
Para ello, implementamos pruebas que verifican
que nuestro programa genera los resultados que de l esperamos.

Conforme vamos aadindole nueva funcionalidad a un programa,


creamos nuevas pruebas con las que podemos medir nuestro progreso
y comprobar que lo que antes funcionaba sigue funcionando tras haber
realizado cambios en el cdigo (test de regresin).
Las pruebas tambin son de vital importancia cuando refactorizamos
(aunque no aadamos nueva funcionalidad, estamos modificando la
estructura interna de nuestro programa y debemos comprobar que no
introducimos errores al refactorizar).

Automatizacin de las pruebas


Para agilizar la realizacin de las pruebas resulta prctico que un test
sea completamente automtico y compruebe los resultados esperados.

No es muy apropiado llamar a una funcin, guardar el resultado


en algn sitio y despus tener que comprobar manualmente si el
resultado era el deseado.

Mantener automatizado un conjunto amplio de tests permite


reducir el tiempo que se tarda en depurar errores y en verificar la
correccin del cdigo.

Tcnicas tiles en el desarrollo de software - 14 -

Fernando Berzal

JUnit
Herramienta especialmente diseada para implementar y automatizar
la realizacin de pruebas de unidad en Java.

Dada una clase de nuestra aplicacin


En una clase aparte definimos un conjunto de casos de prueba
- La clase hereda de junit.framework.TestCase
- Cada caso de prueba se implementa en un mtodo aparte.
- El nombre de los casos de prueba siempre comienza por test.
import junit.framework.*;
public class CuentaTest extends TestCase
{

Cada caso de prueba invoca a una serie de mtodos de nuestra clase


y comprueba los resultados que se obtienen tras invocarlos.
- Creamos uno o varios objetos de nuestra clase con new
- Realizamos operaciones con ellos.
- Definimos aserciones (condiciones que han de cumplirse).
public void testCuentaNueva ()
{
Cuenta cuenta = new Cuenta();
assertEquals(cuenta.getSaldo(), 0.00);
}
public void testIngreso ()
{
Cuenta cuenta = new Cuenta();
cuenta.ingresar(100.00);
assertEquals(cuenta.getSaldo(), 100.00);
}

Tcnicas tiles en el desarrollo de software - 15 -

Fernando Berzal

Finalmente, ejecutamos los casos de prueba con JUnit:


Si todos los casos de prueba funcionan correctamente

Si algn caso de prueba falla

Tendremos que localizar el error y corregirlo


con ayuda de los mensajes que nos muestra JUnit.

MUY IMPORTANTE: Que nuestra implementacin supere todos los


casos de prueba no quiere decir que sea correcta; slo quiere decir que
funciona correctamente para los casos de prueba que hemos diseado.
Tcnicas tiles en el desarrollo de software - 16 -

Fernando Berzal

Apndice: Cmo ejecutar JUnit desde nuestro propio cdigo


Para lanzar JUnit desde nuestro propio cdigo,
sin tener que ejecutar la herramienta a mano,
hemos de implementar el mtodo main en nuestra clase
y definir un sencillo constructor.

import junit.framework.*;
public class CuentaTest extends TestCase
{
public static void main(String args[])
{
junit.swingui.TestRunner.main (
new String[] {"CuentaTest"});
}
public CuentaTest(String name)
{
super(name);
}
// Casos de prueba

Tcnicas tiles en el desarrollo de software - 17 -

Fernando Berzal

Ejemplo: La clase Money


Basado en Test-Driven Development by Example, pp. 1-87 Kent Beck

Vamos a definir una clase, denominada Money, para representar


cantidades de dinero que pueden estar expresadas en distintas monedas
Por ejemplo, queremos usar esta clase para generar informes como
Empresa
Telefnica
Vodafone

Acciones
200
100

Precio
10 EUR
50 EUR

Total
2000 EUR
5000 EUR
7000 EUR

El problema es que tambin nos podemos encontrar con situaciones


como la siguiente
Empresa
Microsoft
Indra

Acciones
200
100

Precio
13 USD
50 EUR

Total
2600 USD
5000 EUR
7000 EUR

donde hemos tenido que utilizar el tipo de cambio actual (1=$1.30)


Comenzamos creando una clase para representar cantidades de dinero:
public class Money
{
private int cantidad;
private String moneda;
public Money (int cantidad, String moneda)
{
this.cantidad = cantidad;
this.moneda = moneda;
}
public int
getCantidad() { return cantidad; }
public String getMoneda()
{ return moneda;
}
}
Tcnicas tiles en el desarrollo de software - 18 -

Fernando Berzal

Una de las cosas que tendremos que hacer es sumar cantidades, por lo
que podemos idear un caso de prueba como el siguiente:
import junit.framework.*;
public class MoneyTest extends TestCase
{
public void testSumaSimple()
{
Money m10 = new Money (10, "EUR");
Money m20 = new Money (20, "EUR");
Money esperado = new Money (30, "EUR");
Money resultado = m10.add(m20);
Assert.assertEquals(resultado,esperado);
}
}

Al idear el caso de prueba, nos estamos fijando en cmo tendremos


que usar nuestra clase en la prctica, lo que nos es extremadamente
til para definir su interfaz.
En este caso, nos hace falta aadir un mtodo add a la clase Money
para poder compilar y ejecutar el caso de prueba
Creamos una implementacin inicial de este mtodo:
public Money add (Money m)
{
int total = getCantidad() + m.getCantidad();
return new Money( total, getMoneda());
}

Compilamos y ejecutamos el test para llevarnos una sorpresa

Tcnicas tiles en el desarrollo de software - 19 -

Fernando Berzal

El caso de prueba falla porque la comparacin de objetos en Java, por


defecto, se limita a comparar referencias (no compara el estado de los
objetos, que es lo que podramos pensar [errneamente]).
La comparacin de objetos en Java se realiza con el mtodo equals,
que puede recibir como parmetro un objeto cualquiera.
Por tanto, hemos de definir el mtodo equals en la clase Money:
public boolean equals (Object obj)
{
Money
aux;
boolean iguales;
if (obj instanceof Money) {
aux = (Money) obj;
iguales = aux.getMoneda().equals(getMoneda())
&& (aux.getCantidad() == getCantidad());
} else {
iguales = false;
}
return iguales;
}

Volvemos a ejecutar el caso de prueba

y ahora s podemos seguir avanzando


Tcnicas tiles en el desarrollo de software - 20 -

Fernando Berzal

De todas formas, para asegurarnos de que todo va bien, creamos un


caso de prueba especfico que verifique el funcionamiento de equals
public void testEquals()
{
Money m10 = new Money (10, "EUR");
Money m20 = new Money (20, "EUR");
Assert.assertEquals(m10,m10);
Assert.assertEquals(m20,m20);
Assert.assertTrue(!m10.equals(m20));
Assert.assertTrue(!m20.equals(m10));
Assert.assertTrue(!m10.equals(null));
}

Al ejecutar nuestros dos casos de prueba con JUNIT


vemos que todo marcha como esperbamos.

Sin embargo, comenzamos a ver que existe cdigo duplicado


(y ya sabemos que eso no es una buena seal),
por lo que utilizamos la posibilidad que nos ofrece JUNIT
de definir variables de instancia en la clase que hereda de TestCase
(variables que hemos de inicializar en el mtodo setUp())
public class MoneyTest extends TestCase
{
Money m10;
Money m20;
public void setUp()
{
m10 = new Money (10, "EUR");
m20 = new Money (20, "EUR");
}

Tcnicas tiles en el desarrollo de software - 21 -

Fernando Berzal

Aparte de sumar cantidades de dinero, tambin tenemos que ser


capaces de multiplicar una cantidad por un nmero entero
(p.ej. nmero de acciones por precio de cada accin)
Podemos aadir un nuevo caso de prueba que utilice esta funcin:
public void testMultiplicar ()
{
Assert.assertEquals ( m10.times(2), m20 );
Assert.assertEquals ( m10.times(2), m20 );
Assert.assertEquals ( m10.times(10), m20.times(5));
}

Obviamente, tambin tendremos que definir times en Money:


public Money times (int n)
{
return new Money ( n*getCantidad(), getMoneda() );
}

Compilamos y ejecutamos los casos de prueba con JUnit:

Poco a poco, vamos aadindole funcionalidad a nuestra clase:


Cada vez que hacemos cambios, volvemos a ejecutar todos
los casos de prueba para confirmar que no hemos estropeado nada.
Tcnicas tiles en el desarrollo de software - 22 -

Fernando Berzal

Una vez que hemos comprobado que ya somos capaces de hacer


operaciones cuando todo se expresa en la misma moneda, tenemos que
comenzar a trabajar con distintas monedas.
Por ejemplo:
public void testSumaCompleja ()
{
Money euros
= new Money(100,"EUR");
Money dollars
= new Money(130,"USD");
Money resultado = euros.add (dollars);
Money banco
= Bank.exchange(dollars,"EUR")
Money esperado = euros.add(banco);
Assert.assertEquals ( resultado, esperado );
}

Para hacer el cambio de moneda, suponemos que tenemos acceso a un


banco que se encarga de hacer la conversin. Hemos de crear una
clase auxiliar Bank que se va a encargar de consultar los tipos de
cambio y aplicar la conversin correspondiente:
public class Bank
{
public static Money exchange
(Money dinero, String moneda)
{
int cantidad = 0;
if (dinero.getMoneda().equals(moneda)) {
cantidad = dinero.getCantidad();
} else if ( dinero.getMoneda().equals("EUR")
&& moneda.equals("USD")) {
cantidad = (130*dinero.getCantidad())/100;
} else if ( dinero.getMoneda().equals("USD")
&& moneda.equals("EUR")) {
cantidad = (100*dinero.getCantidad())/130;
}
return new Money(cantidad,moneda);
}
}
Tcnicas tiles en el desarrollo de software - 23 -

Fernando Berzal

Por ahora, nos hemos limitado a realizar una conversin fija para
probar el funcionamiento de nuestra clase Money (en una aplicacin
real tendramos que conectarnos realmente con el banco).
Obviamente, al ejecutar nuestros casos de prueba se produce un error:

Hemos de corregir la implementacin interna del mtodo add de la


clase Money para que tenga en cuenta el caso de que las cantidades
correspondan a monedas diferentes:
public Money add (Money dinero)
{
Money convertido;
int
total;
if (getMoneda().equals(dinero.getMoneda()))
convertido = dinero;
else
convertido = Bank.exchange(dinero, getMoneda());
total = getCantidad() + convertido.getCantidad();
return new Money( total, getMoneda());
}

Tcnicas tiles en el desarrollo de software - 24 -

Fernando Berzal

Volvemos a ejecutar los casos de prueba


y comprobamos que, ahora s, las sumas se hacen correctamente:

Si todava no las tuvisemos todas con nosotros,


podramos seguir aadiendo casos de prueba para adquirir
ms confianza en la implementacin que acabamos de realizar.
Por ejemplo, el siguiente caso de prueba comprueba
el funcionamiento del banco al realizar conversiones de divisas:
public void testBank ()
{
Money euros
= new Money(10,"EUR");
Money dollars
= new Money(13,"USD");
Assert.assertEquals (
Bank.exchange(dollars,"EUR"), euros );
Assert.assertEquals (
Bank.exchange(dollars,"USD"), dollars );
Assert.assertEquals (
Bank.exchange(euros, "EUR"), euros );
Assert.assertEquals (
Bank.exchange(euros, "USD"), dollars );
}
Tcnicas tiles en el desarrollo de software - 25 -

Fernando Berzal

Comentarios finales: El mtodo toString


Para que resulte ms fcil interpretar
los mensajes generados por JUNIT,
resulta recomendable definir el mtodo toString()
en todas las clases que definamos. Por ejemplo:
public class Money
{

public String toString ()


{
return getCantidad()+" "+getMoneda();
}
}

RECORDATORIO: toString() es un mtodo


que se emplea en Java para convertir un objeto cualquiera
en una cadena de caracteres.

Teniendo definido el mtodo anterior,


en nuestras aplicaciones podramos escribir directamente

Money share = new Money(13,"USD");


Money investment = share.times(200);
Money euros = Bank.exchange(investment,EUR);
System.out.println(investment + "(" + euros + ")");

y obtener como resultado en pantalla:


2600 USD (2000 EUR)

Tcnicas tiles en el desarrollo de software - 26 -

Fernando Berzal

TDD
[Test-Driven Development]
Consiste en implementar las pruebas de unidad
antes incluso de comenzar a escribir el cdigo de un mdulo.

Las pruebas de unidad consisten en


comprobaciones (manuales o automatizadas)
que se realizan para verificar que el cdigo
correspondiente a un mdulo concreto de un sistema software
funciona de acuerdo con los requisitos del sistema.

Tradicionalmente,
las pruebas se realizan a posteriori
Los casos de prueba se suelen escribir despus de implementar el
mdulo cuyo funcionamiento pretenden verificar.
Como mucho, se preparan en paralelo si el programador
y la persona que realiza las pruebas [tester] no son la misma persona.

En TDD,
las pruebas se preparan antes de comenzar a escribir el cdigo.
Primero escribimos un caso de prueba
y slo despus implementamos el cdigo necesario
para que el caso de prueba se pase con xito

Tcnicas tiles en el desarrollo de software - 27 -

Fernando Berzal

Aunque pueda parecer extrao, TDD ofrece algunas ventajas:

Al escribir primero los casos de prueba, definimos de manera


formal los requisitos que esperamos que cumpla nuestra aplicacin.
Los casos de prueba sirven de documentacin del sistema.

Al escribir una prueba de unidad, pensamos en la forma correcta de


utilizar un mdulo que an no existe.
Hacemos hincapi en el diseo de la interfaz de un mdulo antes
de centrarnos en su implementacin (algo siempre bueno:
la interfaz debe determinar la implementacin, y no al revs).

La ejecucin de los casos de prueba se realiza de forma


automatizada (por ejemplo, con ayuda de JUNIT)
Al ejecutar los casos de prueba detectamos si hemos introducido
algn error al tocar el cdigo para realizar cualquier cambio en
nuestra aplicacin (ya sea para aadirle nuevas funciones o para
reorganizar su estructura interna [refactorizacin]).

Los casos de prueba nos permiten perder el miedo a realizar


modificaciones en el cdigo
Tras realizar pequeas modificaciones sobre el cdigo,
volveremos a ejecutar los casos de prueba para comprobar
inmediatamente si hemos cometido algn error o no.

Los casos de prueba definen claramente cundo termina nuestro


trabajo (cuando se pasan con xito todas los casos de prueba).

Tcnicas tiles en el desarrollo de software - 28 -

Fernando Berzal

El proceso de construccin de software se convierte en un ciclo:


1. Aadir un nuevo caso de prueba
que recoja algo que nuestro mdulo debe realizar correctamente.

2. Ejecutar los casos de prueba


para comprobar que el caso recin aadido falla.

3. Realizar pequeos cambios en la implementacin


(en funcin de lo que queremos que haga nuestra aplicacin).

4. Ejecutar los casos de prueba


hasta que todos se vuelven a pasar con xito.

5. Refactorizar el cdigo para mejorar su diseo (eliminar cdigo


duplicado, extraer mtodos, renombrar identificadores)

6. Ejecutar los casos de prueba


para comprobar que todo sigue funcionando correctamente.

7. Volver al paso inicial


Tcnicas tiles en el desarrollo de software - 29 -

Fernando Berzal

Caso prctico: Bolera

El problema consiste en
obtener la puntuacin de un jugador en una partida de bolos.

Una posible solucin


y el proceso seguido para obtenerla en

The Bowling Game. An example of test-first pair programming


Robert C. Martin & Robert S. Koss, 2001
http://www.objectmentor.com/resources/articles/xpepisode.htm

Robert C. Martin:
Agile Software Development: Principles, Patterns, and Practices.
Prentice Hall, 2003. ISBN 0-13-597444-5.

Tcnicas tiles en el desarrollo de software - 30 -

Fernando Berzal

Clases y objetos
Encapsulacin
Herencia
Redefinicin de mtodos y polimorfismo
El Principio de Sustitucin de Liskov
Acerca de la sobrecarga de mtodos
Un ejemplo clsico: Figuras geomtricas
La palabra reservada final
Organizacin de las clases
Organizacin fsica: ficheros
Organizacin lgica: paquetes
Modificadores de acceso
Caso prctico: Vdeo-club

Encapsulacin
RECORDATORIO
Clases
Una clase es la especificacin de un tipo de dato.
Una clase sirve
tanto de mdulo (unidad de descomposicin del software)
como de tipo

(descripcin de las caractersticas con las


equipamos a los objetos de un conjunto).

y objetos
Un objeto es una instancia de una clase.
Un objeto encapsula:
- Datos (atributos que le sirven para mantener su estado).
- Operaciones (mtodos que definen su comportamiento).
Un objeto es una entidad autnoma
con una funcionalidad concreta y bien definida.
Al programar, definimos una clase para especificar cmo se
comportan y mantienen su estado los objetos de esa clase:
Todos los objetos de una misma clase comparten
sus atributos y el comportamiento que exhiben.
Una clase no es ms que una especificacin, por lo que para
usarla hemos de instanciarla:
Se crean tantos objetos de la clase como nos haga falta.
Cada objeto proporcionar un servicio que podr ser
utilizado por otros objetos de nuestro sistema.
OOP Clases y objetos: Java

-1-

Fernando Berzal

Herencia
Hay clases que comparten gran parte de sus caractersticas.

El mecanismo conocido con el nombre de herencia


permite reutilizar clases: Se crea una nueva clase
que extiende la funcionalidad de una clase existente
sin tener que reescribir el cdigo asociado a esta ltima.

La nueva clase, a la que se denomina subclase, puede poseer


atributos y mtodos que no existan en la clase original.
Los objetos de la nueva clase heredan los atributos y los
mtodos de la clase original, que se denomina superclase.

Trabajador es una clase genrica que sirve para almacenar


datos como el nombre, la direccin, el nmero de telfono
o el nmero de la seguridad social de un trabajador.
Empleado es una clase especializada para representar los
empleados que tienen una nmina mensual (encapsula datos
como su salario anual o las retenciones del IRPF).
Consultor es una clase especializada para representar a
aquellos trabajadores que cobran por horas (por ejemplo,
registra el nmero de horas que ha trabajado un consultor
y su tarifa horaria).
OOP Clases y objetos: Java

-2-

Fernando Berzal

Las clases Empleado y Consultor,


adems de los atributos y de las operaciones que definen,
heredan de Trabajador todos sus atributos y operaciones.

Un empleado concreto tendr,


adems de sus atributos y operaciones como Empleado,
todos los atributos correspondientes a la superclase Trabajador.
OOP Clases y objetos: Java

-3-

Fernando Berzal

En Java:
import java.util.Date;

// Para las fechas

public class Trabajador


{
private String nombre;
private String puesto;
private String direccion;
private String telefono;
private Date
fecha_nacimiento;
private Date
fecha_contrato;
private String NSS;
// Constructor
public Trabajador (String nombre, String NSS)
{
this.nombre = nombre;
this.NSS = NSS;
}
// Mtodos get & set
// ...
// Comparacin de objetos
public boolean equals (Trabajador t)
{
return this.NSS.equals(t.NSS);
}
// Conversin en una cadena de caracteres
public String toString ()
{
return nombre + " (NSS "+NSS+")";
}
}

NOTA:

OOP Clases y objetos: Java

Siempre es recomendable definir


los mtodos equals() y toString()
-4-

Fernando Berzal

public class Empleado extends Trabajador


{
private double sueldo;
private double impuestos;
private final int PAGAS = 14;
// Constructor
public Empleado
(String nombre, String NSS, double sueldo)
{
super(nombre,NSS);
this.sueldo
= sueldo;
this.impuestos = 0.3 * sueldo;
}
// Nmina
public double calcularPaga ()
{
return (sueldo-impuestos)/PAGAS;
}
// toString
public String toString ()
{
return "Empleado "+super.toString();
}
}

Con la palabra reservada extends indicamos que


Empleado es una subclase de Trabajador.
Con la palabra reservada super accedemos a miembros
de la superclase desde la subclase.
Generalmente, en un constructor, lo primero que nos
encontramos es una llamada al constructor de la clase
padre con super(). Si no ponemos nada, se llama al
constructor por defecto de la superclase antes de
ejecutar el constructor de la subclase.
OOP Clases y objetos: Java

-5-

Fernando Berzal

class Consultor extends Trabajador


{
private int
horas;
private double tarifa;
// Constructor
public Consultor (String nombre, String NSS,
int horas, double tarifa)
{
super(nombre,NSS);
this.horas = horas;
this.tarifa = tarifa;
}
// Paga por horas
public double calcularPaga ()
{
return horas*tarifa;
}
// toString
public String toString ()
{
return "Consultor "+super.toString();
}
}

La clase Consultor tambin define un mtodo llamado


calcularPaga(), si bien en este caso el clculo se hace
de una forma diferente por tratarse de un trabajador de un
tipo distinto.
Tanto la clase Empleado como la clase Consultor
redefinen el mtodo toString() que convierte un objeto
en una cadena de caracteres.
De hecho, Trabajador tambin redefine este
mtodo, que se hereda de la clase Object, la clase
base de la que heredan todas las clases en Java.
OOP Clases y objetos: Java

-6-

Fernando Berzal

Redefinicin de mtodos
Como hemos visto en el ejemplo con el mtodo toString(),
cada subclase hereda las operaciones de su superclase
pero tiene la posibilidad de modificar localmente el
comportamiento de dichas operaciones (redefiniendo mtodos).
// Declaracin de variables
Trabajador trabajador;
Empleado
empleado;
Consultor consultor;
// Creacin de objetos
trabajador = new Trabajador ("Juan", "456");
empleado = new Empleado

("Jose", "123", 24000.0);

consultor = new Consultor ("Juan", "456", 10, 50.0);

// Salida estndar con toString()


System.out.println(trabajador);
Juan (NSS 456)
System.out.println(empleado);
Empleado Jose (NSS 123)
System.out.println(consultor);
Consultor Juan (NSS 456)

// Comparacin de objetos con equals()


System.out.println(trabajador.equals(empleado));
false
System.out.println(trabajador.equals(consultor));
true
OOP Clases y objetos: Java

-7-

Fernando Berzal

Polimorfismo
Al redefinir mtodos, objetos de diferentes tipos
pueden responder de forma diferente a la misma llamada
(y podemos escribir cdigo de forma general sin preocuparnos
del mtodo concreto que se ejecutar en cada momento).
Ejemplo
Podemos aadirle a la clase Trabajador un mtodo
calcularPaga genrico (que no haga nada por ahora):

public class Trabajador


public double calcularPaga ()
{
return 0.0;
// Nada por defecto
}

En las subclases de Trabajador, no obstante, s que definimos el


mtodo calcularPaga() para que calcule el importe del pago
que hay que efectuarle a un trabajador (en funcin de su tipo).

public class Empleado extends Trabajador


public double calcularPaga ()
{
return (sueldo-impuestos)/PAGAS;
}

// Nmina

class Consultor extends Trabajador


public double calcularPaga ()
{
return horas*tarifa;
}

OOP Clases y objetos: Java

-8-

// Por horas

Fernando Berzal

Como los consultores y los empleados son trabajadores, podemos


crear un array de trabajadores con consultores y empleados:

Trabajador trabajadores[] = new Trabajador[2];


trabajadores[0] = new Empleado
("Jose", "123", 24000.0);
trabajadores[1] = new Consultor
("Juan", "456", 10, 50.0);

Una vez que tenemos un vector con todos los trabajadores de una
empresa, podramos crear un programa que realizase los pagos
correspondientes a cada trabajador de la siguiente forma:

public void pagar (Trabajador trabajadores[])


{
int i;
for (i=0; i<trabajadores.length; i++)
realizarTransferencia ( trabajadores[i],
trabajadores[i].calcularPaga());
}

Para los trabajadores del vector


anterior,
se
realizara


























una transferencia de 1200
 
!#"
%$&"'(
otra transferencia, esta vez de 500

Cada vez que se invoca el mtodo calcularPaga(), se busca


automticamente el cdigo que en cada momento se ha de
ejecutar en funcin del tipo de trabajador (enlace dinmico).
La bsqueda del mtodo que se ha de invocar como respuesta a
un mensaje dado se inicia con la clase del receptor. Si no se
encuentra un mtodo apropiado en esta clase, se busca en su clase
padre (de la hereda la clase del receptor). Y as sucesivamente
hasta encontrar la implementacin adecuada del mtodo que se ha
de ejecutar como respuesta a la invocacin original.
OOP Clases y objetos: Java

-9-

Fernando Berzal

El Principio de Sustitucin de Liskov


Debe ser posible utilizar cualquier objeto instancia de una
subclase en el lugar de cualquier objeto instancia de su
superclase sin que la semntica del programa escrito en los
trminos de la superclase se vea afectado.
Barbara H. Liskov & Stephen N. Zilles:
Programming with Abstract Data Types
Computation Structures Group, Memo No 99, MIT, Project MAC, 1974.
(ACM SIGPLAN Notices, 9, 4, pp. 50-59, April 1974.)

El cumplimiento del Principio de Sustitucin de Liskov


permite obtener un comportamiento y diseo coherente:
Ejemplo
Cuando tengamos trabajadores,
sean del tipo particular que sean,
el mtodo calcularPaga() siempre calcular
el importe del pago que hay que efectuar
en compensacin por los servicios del trabajador.

Acerca de la sobrecarga de mtodos


No hay que confundir el polimorfismo con la sobrecarga de mtodos
(distintos mtodos con el mismo nombre pero diferentes parmetros).
Ejemplo
Podemos definir varios constructores
para crear de distintas formas objetos de una misma clase.
OOP Clases y objetos: Java

- 10 -

Fernando Berzal

Un ejemplo clsico: Figuras geomtricas

public class Figura


{
protected double x;
protected double y;
protected Color color;
protected Panel panel;

public Figura (Panel panel, double x, double y)


{
this.panel = panel;
this.x
= x;
this.y
= y;
}
public void setColor (Color color)
{
this.color = color;
panel.setColor(color);
}
public void dibujar ()
{
// No hace nada aqu
}
}
OOP Clases y objetos: Java

- 11 -

Fernando Berzal

public class Circulo extends Figura


{
private double radio;
public Circulo(Panel panel,
double x, double y, double radio)
{
super(panel,x,y);
this.radio = radio;
}
public void dibujar ()
{
panel.drawEllipse(x,y, x+2*radio, y+2*radio);
}
}

public class Cuadrado extends Figura


{
private double lado;
public Cuadrado(Panel panel,
double x, double y, double lado)
{
super(panel,x,y);
this.lado = lado;
}
public void dibujar ()
{
panel.drawRectangle(x,y, x+lado, y+lado);
}
}

OOP Clases y objetos: Java

- 12 -

Fernando Berzal

La palabra reservada final


En Java, usando la palabra reservada final, podemos:
1. Evitar que un mtodo se pueda redefinir en una subclase:
class Consultor extends Trabajador
{

public final double calcularPaga ()


{
return horas*tarifa;
}

}
Aunque creemos subclases de Consultor, el dinero

que se le pague siempre ser en funcin de las horas


que trabaje y de su tarifa horaria (y eso no podremos
cambiarlo aunque queramos).

2. Evitar que se puedan crear subclases de una clase dada:


public final class Circulo extends Figura

public final class Cuadrado extends Figura

Al usar final, tanto Circulo como Cuadrado son


ahora clases de las que no se pueden crear subclases.
En ocasiones, una clase ser final
porque no tenga sentido crear subclases o, simplemente,
porque deseamos que la clase no se pueda extender.

RECORDATORIO:
En Java, final tambin se usa para definir constantes simblicas.
OOP Clases y objetos: Java

- 13 -

Fernando Berzal

Organizacin de las clases


Organizacin fsica: Ficheros
En Java, el cdigo correspondiente a cualquier clase pblica ha de
estar definida en un fichero independiente con extensin .java.
El nombre del fichero ha de coincidir con el nombre de la clase.

En ocasiones, en un fichero se pueden incluir varias clases si slo


una de ellas es pblica (esto es, las dems son nicamente clases
auxiliares que utilizamos para implementar la funcionalidad
correspondiente a la clase pblica).
Ejemplo
Las clases que se utilizan para implementar manejadores de
eventos en aplicaciones con interfaces grficas de usuario.

Una vez compilada, una clase, sea pblica o no, da lugar a un


fichero con extensin .class en el que se almacenan los
bytecodes correspondientes al cdigo de la clase.
Cuando ejecutemos una aplicacin que utilice una clase
particular, el fichero .class correspondiente a la clase debe ser
accesible a partir del valor que tenga en ese momento la variable
de entorno CLASSPATH:
El fichero .class debe encontrarse en una de las
carpetas/directorios incluidos en el CLASSPATH.
Java tambin permite incluir ficheros comprimidos en el
CLASSPATH, en formato ZIP, con extensin .zip o .jar,
por lo que el fichero .class puede encontrarse dentro de
uno de los ficheros de este tipo incluidos en el CLASSPATH.
OOP Clases y objetos: Java

- 14 -

Fernando Berzal

Organizacin lgica: Paquetes


Las clases en Java se agrupan en paquetes.
Todas las clases compiladas en el mismo directorio (carpeta)
se consideran pertenecientes a un mismo paquete.
El paquete al que pertenece una clase se indica al comienzo del
fichero en el que se define la clase con la palabra reservada
package.
El nombre del paquete ha de cumplir las mismas normas que
cualquier otro identificador en Java.

package economics;
public class Demanda
{
private double pendiente;
private double precioMaximo;

public Demanda (double precioMax, double pendiente)


{
this.pendiente = pendiente;
this.precioMaximo = precioMaximo;
}

public double getPrecio (long cantidad)


{
return precioMaximo + cantidad*pendiente;
}
public long getCantidadDemandada (double precio)
{
return (long) ((precio-precioMaximo)/pendiente);
}
}
OOP Clases y objetos: Java

- 15 -

Fernando Berzal

Cuando una clase pertenece a un paquete (p.ej. economics), el


fichero .java ha de colocarse en un subdirectorio del directorio
que aparezca en el CLASSPATH (p.ej. personal/economics si
personal es lo que aparece en el CLASSPATH).
Los paquetes se pueden organizar de forma jerrquica, de
forma que economics.markets ser un subpaquete del
paquete economics
Los ficheros .java/.class correspondientes debern
colocarse en el directorio personal/economics/markets
Cuando usamos una clase que no est en el mismo paquete en
el que nos encontramos, hemos de incluir una sentencia
import al comienzo del fichero .java o utilizar el nombre
completo de la clase a la que hacemos referencia en el cdigo
(esto es, paquete.Clase).

package economics.markets;
public class AnalisisEconomico
{
private economics.Demanda demanda;
private economics.Costes
costes;
private economics.Ingresos ingresos;

o bien
package economics.markets;
import economics.*;
public class AnalisisEconomico
{
private Demanda demanda;
private Costes
costes;
private Ingresos ingresos;

}
OOP Clases y objetos: Java

- 16 -

Fernando Berzal

Ejemplo
La biblioteca de clases estndar de Java
incluye cientos de clases organizadas en multitud de paquetes:

Paquete
java.lang

java.awt
java.applet
java.io

java.util

java.net
java.rmi

Descripcin
Clases centrales de la plataforma Java
(nmeros, cadenas y objetos).
No es necesario incluir la sentencia import
cuando se usan clases de este paquete.
Clases para crear interfaces grficas
y dibujar figuras e imgenes.
Clases necesarias para crear applets.
Clases para realizar operaciones de
entrada/salida (p.ej. uso de ficheros).
Utilidades varias:
fechas, generadores de nmeros aleatorios,
vectores de tamao dinmico, etctera.
Para implementar aplicaciones distribuidas
(que funcionen en redes de ordenadores).
Para crear aplicaciones distribuidas con mayor
comodidad [Remote Method Invocation].

java.sql

Clases necesarias para acceder a bases de datos.

javax.swing

Para crear interfaces grficas de usuario con


componentes 100% escritos en Java.

OOP Clases y objetos: Java

- 17 -

Fernando Berzal

Modificadores de acceso
Se pueden establecer distintos niveles de encapsulacin
para los miembros de una clase (atributos y operaciones) en
funcin de desde dnde queremos que se pueda acceder a ellos:

Visibilidad Significado
Se puede acceder al
Pblica
miembro de la clase
desde cualquier lugar.
Slo se puede acceder
al miembro de la clase
desde la propia clase o
Protegida
desde una clase que
herede de ella.
Se puede acceder a los
miembros de una clase
Por defecto
desde cualquier clase
en el mismo paquete
Slo se puede acceder
Privada
al miembro de la clase
desde la propia clase.

Java

UML

public

protected

private

La encapsulacin
permite agrupar datos y operaciones en un objeto,
de tal forma los detalles del objeto se ocultan a sus usuarios
(ocultamiento de informacin):

A un objeto se accede a travs de sus mtodos pblicos (su


interfaz), por lo que no es necesario conocer su implementacin.

OOP Clases y objetos: Java

- 18 -

Fernando Berzal

Para encapsular el estado de un objeto,


sus atributos se declaran como variables de instancia privadas.
package economics;
public class Costes
{
private double costeInicial;
private double costeMarginal;

Como consecuencia, se han de emplear mtodos get para


permitir que se pueda acceder al estado de un objeto:
public class Costes
public double getCosteInicial ()
{
return costeInicial;
}
public double getCosteMarginal ()
{
return costeMarginal;
}

Si queremos permitir que se pueda modificar el estado de un


objeto desde el exterior, implementaremos mtodos set:
public class Costes
public void setCosteInicial (double inicial)
{
this.costeInicial = inicial;
}
public void setCosteMarginal (double marginal)
{
this.costeMarginal = marginal;
}
OOP Clases y objetos: Java

- 19 -

Fernando Berzal

OBSERVACIONES FINALES:

Que los miembros de una clase sean privados quiere decir


que no se puede acceder a ellos desde el exterior de la clase
(ni siquiera desde sus propias subclases), lo que permite
mantener la encapsulacin de los objetos.

La visibilidad protegida relaja esta restriccin ya que permite


acceder a los miembros de una clase desde sus subclases.
No obstante, su uso tiende a crear jerarquas de clases
fuertemente acopladas, algo que procuraremos evitar.

public class Figura


{
protected double x;
protected double y;
protected Color color;
protected Panel panel;

}
public class Cuadrado extends Figura
{

// Desde cualquier sitio de la implementacin


// de la clase Cuadrado se puede acceder a los
// miembros protegidos de la clase Figura

p.ej. Si tuvisemos que localizar un error que afectase


al color de la figura no bastara con examinar el
cdigo de la clase Figura. Tambin tendramos
que analizar el uso que se hace del atributo color
en todas las subclases de Figura.
OOP Clases y objetos: Java

- 20 -

Fernando Berzal

Caso prctico
Alquiler de pelculas en un vdeo-club
Adaptado de Refactoring Martin Fowler, 2000

Supongamos que tenemos que desarrollar una aplicacin


que gestione los alquileres de DVDs en un vdeo-club.

Inicialmente, nuestro diagrama de clases sera similar al siguiente:

public class DVD


{
// Constantes simblicas
public static final int INFANTIL = 2;
public static final int NORMAL
= 0;
public static final int NOVEDAD = 1;
// Variables de instancia
private String _titulo;
private int
_tipo;
// Constructor
public DVD (String titulo, int tipo)
{
_titulo = titulo;
_tipo
= tipo;
}
OOP - Caso prctico: Vdeo-club

-1-

Fernando Berzal

// Acceso a las variables de instancia


public int getTipo()
{
return _tipo;
}
public void setTipo (int tipo)
{
_tipo = tipo;
}
public String getTitulo ()
{
return _titulo;
}
}

public class Alquiler


{
private DVD _dvd;
private int _tiempo;
public Alquiler (DVD dvd, int tiempo)
{
_dvd = dvd;
_tiempo = tiempo;
}
public int getTiempo()
{
return _tiempo;
}
public DVD getDVD()
{
return _dvd;
}
}
OOP - Caso prctico: Vdeo-club

-2-

Fernando Berzal

import java.util.Vector;

public class Cliente


{
// Variables de instancia
private String _nombre;
private Vector _alquileres =new Vector();
// Constructor
public Cliente (String nombre)
{
_nombre = nombre;
}
// Acceso a las variables de instancia
public String getNombre()
{
return _nombre;
}
// Registrar alquiler
public void nuevoAlquiler (Alquiler alquiler)
{
_alquileres.add(alquiler);
}
// Emitir un informe del cliente
public String
{
double
double
int
int
Alquiler
String

informe()
total;
importe;
puntos;
i;
alquiler;
salida;

total = 0;
puntos = 0;
salida = "Informe para " + getNombre() + "\n";

OOP - Caso prctico: Vdeo-club

-3-

Fernando Berzal

// Recorrido del vector de alquileres


for (i=0; i<_alquileres.size(); i++) {
importe = 0;
alquiler = (Alquiler) _alquileres.get(i);
// Importe del alquiler
switch (alquiler.getDVD().getTipo()) {
case DVD.NORMAL:
importe += 2;
if (alquiler.getTiempo()>2)
importe += (alquiler.getTiempo()-2)*1.5;
break;
case DVD.NOVEDAD:
importe += alquiler.getTiempo() * 3;
break;
case DVD.INFANTIL:
importe += 1.5;
if (alquiler.getTiempo()>3)
importe += (alquiler.getTiempo()-3)*1.5;
break;
}
// Programa de puntos
puntos++;
if ( (alquiler.getDVD().getTipo()==DVD.NOVEDAD)
&& (alquiler.getTiempo()>1) )
puntos++;
// Bonificacin
// Mostrar detalles del alquiler
salida += "\t" + alquiler.getDVD().getTitulo()
+ "\t" + String.valueOf(importe) + " \n";
// Acumular total
total += importe;
}
OOP - Caso prctico: Vdeo-club

-4-

Fernando Berzal

// Pie del informe


salida += "IMPORTE TOTAL = "
+ String.valueOf(total) + "

\n";

salida += "Dispone de "


+ String.valueOf(puntos) + " puntos\n";
return salida;
}
}

Paso 1: Extraer mtodo de informe()


El mtodo informe es excesivamente largo

public class Cliente


public double precio (Alquiler alquiler)
{
double importe = 0;
switch (alquiler.getDVD().getTipo()) {
case DVD.NORMAL:
importe += 2;
if (alquiler.getTiempo()>2)
importe += (alquiler.getTiempo()-2)*1.5;
break;
case DVD.NOVEDAD:
importe += alquiler.getTiempo() * 3;
break;
case DVD.INFANTIL:
importe += 1.5;
if (alquiler.getTiempo()>3)
importe += (alquiler.getTiempo()-3)*1.5;
break;
}
return importe;
}
OOP - Caso prctico: Vdeo-club

-5-

Fernando Berzal

public String
{
double
double
int
int
Alquiler
String

informe()
total;
importe;
puntos;
i;
alquiler;
salida;

total = 0;
puntos = 0;
salida = "Informe para " + getNombre() +

"\n";

for (i=0; i<_alquileres.size(); i++) {


alquiler = (Alquiler) _alquileres.get(i);
importe = precio(alquiler);
// Programa de puntos
puntos++;
if ((alquiler.getDVD().getTipo()==DVD.NOVEDAD)
&& (alquiler.getTiempo()>1))
puntos++;
// Bonificacin
// Mostrar detalles del alquiler
salida += "\t" + alquiler.getDVD().getTitulo()
+ "\t" + String.valueOf(importe) + " \n";
// Acumular total
total += importe;
}
// Pie del recibo
salida += "IMPORTE TOTAL = "
+ String.valueOf(total) + "

\n";

salida += "Dispone de "


+ String.valueOf(puntos) + " puntos\n";
return salida;
}

OOP - Caso prctico: Vdeo-club

-6-

Fernando Berzal

Debemos comprobar que calculamos correctamente los precios,


para lo que preparamos una batera de casos de prueba:
import junit.framework.*;
public class AlquilerTest extends TestCase
{
private Cliente cliente;
private DVD
casablanca;
private DVD
indy;
private DVD
shrek;
private Alquiler alquiler;
// Infraestructura
public static void main(String args[])
{
junit.swingui.TestRunner.main (
new String[] {"AlquilerTest"});
}
public AlquilerTest(String name)
{
super(name);
}
public void setUp ()
{
cliente = new Cliente("Kane");
casablanca = new DVD("Casablanca", DVD.NORMAL);
indy = new DVD("Indiana Jones XIII", DVD.NOVEDAD);
shrek = new DVD("Shrek", DVD.INFANTIL);
}
// Casos de prueba
public void testNormal1 ()
{
alquiler = new Alquiler(casablanca,1);
assertEquals( cliente.precio(alquiler), 2.0, 0.001);
}
public void testNormal2 ()
{
alquiler = new Alquiler(casablanca,2);
assertEquals( cliente.precio(alquiler), 2.0, 0.001);
}
public void testNormal3 ()
{
alquiler = new Alquiler(casablanca,3);
assertEquals( cliente.precio(alquiler), 3.5, 0.001);
}
OOP - Caso prctico: Vdeo-club

-7-

Fernando Berzal

public void testNormal7 ()


{
alquiler = new Alquiler(casablanca,7);
assertEquals( cliente.precio(alquiler), 9.5, 0.001);
}
public void testNovedad1 ()
{
alquiler = new Alquiler(indy,1);
assertEquals( cliente.precio(alquiler), 3.0, 0.001);
}
public void testNovedad2 ()
{
alquiler = new Alquiler(indy,2);
assertEquals( cliente.precio(alquiler), 6.0, 0.001);
}
public void testNovedad3 ()
{
alquiler = new Alquiler(indy,3);
assertEquals( cliente.precio(alquiler), 9.0, 0.001);
}
public void testInfantil1 ()
{
alquiler = new Alquiler(shrek,1);
assertEquals( cliente.precio(alquiler), 1.5, 0.001);
}
public void testInfantil3 ()
{
alquiler = new Alquiler(shrek,3);
assertEquals( cliente.precio(alquiler), 1.5, 0.001);
}
public void testInfantil4 ()
{
alquiler = new Alquiler(shrek,4);
assertEquals( cliente.precio(alquiler), 3.0, 0.001);
}
public void testInfantil7 ()
{
alquiler = new Alquiler(shrek,7);
assertEquals( cliente.precio(alquiler), 7.5, 0.001);
}
}

11/11
OOP - Caso prctico: Vdeo-club

-8-

Fernando Berzal

Paso 2: Mover el mtodo precio()


En realidad, precio no usa datos de Cliente, por lo que resulta ms
que razonable convertirlo en un mtodo de la clase Alquiler

public class Alquiler


{

public double getPrecio ()


{
double importe = 0;
switch (getDVD().getTipo()) {
case DVD.NORMAL:
importe += 2;
if (getTiempo()>2)
importe += (getTiempo()-2) * 1.5;
break;
case DVD.NOVEDAD:
importe += getTiempo() * 3;
break;
case DVD.INFANTIL:
importe += 1.5;
if (getTiempo()>3)
importe += (getTiempo()-3) * 1.5;
break;
}
return importe;
}
}

Cuando un mtodo de una clase (Cliente) accede continuamente


a los miembros de otra clase (Alquiler) pero no a los de su clase
(Cliente), es conveniente mover el mtodo a la clase cuyos datos
utiliza. Adems, el cdigo resultante ser ms sencillo.

OOP - Caso prctico: Vdeo-club

-9-

Fernando Berzal

Como hemos cambiado precio() de sitio, tenemos que cambiar las


llamadas a precio() que haba en nuestra clase Cliente:
public class Cliente
{

public String informe()


{

for (i=0; i<_alquileres.size(); i++) {


alquiler = (Alquiler) _alquileres.get(i);
importe = alquiler.getPrecio();

}
}

Adems, deberemos actualizar nuestros casos de prueba:


p.ej.
public void testNormal3 ()
{
alquiler = new Alquiler(casablanca,3);
assertEquals( alquiler.getPrecio(), 3.5, 0.001);
}

Cuando hayamos realizado todos los cambios,


volveremos a ejecutar los casos de prueba
para comprobar que todo sigue funcionando correctamente.
11/11

OOP - Caso prctico: Vdeo-club

- 10 -

Fernando Berzal

Paso 3: Extraer el clculo correspondiente al programa de puntos

public class Alquiler


{

public int getPuntos ()


{
int puntos = 1;
// Bonificacin
if ( (getDVD().getTipo() == DVD.NOVEDAD)
&& (getTiempo()>1))
puntos++;
return puntos;
}
}

public class Cliente


{

public String informe()


{

for (i=0; i<_alquileres.size(); i++) {


alquiler = (Alquiler) _alquileres.get(i);
importe = alquiler.getPrecio();
puntos += alquiler.getPuntos();

}
}

OOP - Caso prctico: Vdeo-club

- 11 -

Fernando Berzal

Paso 4: Separar los clculos de las operaciones de E/S


En el mtodo informe(), estamos mezclando clculos tiles con las
llamadas a System.out.println() que generar el informe:

Creamos un mtodo independiente para calcular el gasto total


realizado por un cliente:

public class Cliente


public double getImporteTotal ()
{
int
i;
double
total;
Alquiler alquiler;
total = 0;
for (i=0; i<_alquileres.size(); i++) {
alquiler = (Alquiler) _alquileres.get(i);
total
+= alquiler.getPrecio();
}
return total;
}

OOP - Caso prctico: Vdeo-club

- 12 -

Fernando Berzal

Creamos otro mtodo independiente para calcular los puntos


acumulados por un cliente en el programa de puntos del vdeo-club:

public class Cliente


public int
{
int
int
Alquiler

getPuntos()
i;
puntos;
alquiler;

puntos = 0;
for (i=0; i<_alquileres.size(); i++) {
alquiler = (Alquiler) _alquileres.get(i);
puntos += alquiler.getPuntos();
}
return puntos;
}

Al separar los clculos de las operaciones de E/S,


podemos preparar casos de prueba que comprueben
el funcionamiento correcto del clculo del total
y del programa de puntos del vdeo-club.
- EJERCICIO OOP - Caso prctico: Vdeo-club

- 13 -

Fernando Berzal

Tras los cambios anteriores en la clase Cliente, la generacin del


informe es bastante ms sencilla que antes:

public class Cliente


public String informe()
{
int
i;
Alquiler alquiler;
String
salida;
salida = "Informe para " + getNombre() + "\n";
for (i=0; i<_alquileres.size(); i++) {
alquiler = (Alquiler) _alquileres.get(i);
salida +=
+
+
+
+

"\t"
alquiler.getDVD().getTitulo()
"\t"
String.valueOf(alquiler.getPrecio())
" \n";

}
salida += "IMPORTE TOTAL = "
+ String.valueOf(getImporteTotal())
+ " \n";
salida += "Dispone de "
+ String.valueOf(getPuntos())
+ " puntos\n";
return salida;
}

OOP - Caso prctico: Vdeo-club

- 14 -

Fernando Berzal

Paso 5: Nueva funcionalidad Informes en HTML


Una vez que nuestro mtodo informe() se encarga nicamente de
realizar las tareas necesarias para generar el informe en s, resulta casi
trivial aadirle a nuestra aplicacin la posibilidad de generar los
informes en HTML (el formato utilizado para crear pginas web):

public class Cliente


public String
{
int
Alquiler
String

informeHTML()
i;
alquiler;
salida;

salida = "<H1>Informe para "


+ "<I>" + getNombre() + "</I>"
+ "</H1>\n";
salida += "<UL>";
for (i=0; i<_alquileres.size(); i++) {
alquiler = (Alquiler) _alquileres.get(i);
salida += "<LI>" + alquiler.getDVD().getTitulo()
+ "(" + alquiler.getPrecio() + " )\n";
}
salida += "</UL>";
salida += "<P>IMPORTE TOTAL = "
+ "<B>" + getImporteTotal() + "

</B>\n";

salida += "<P>Dispone de "


+ "<I>" + getPuntos() + " puntos</I>\n";
return salida;
}

OOP - Caso prctico: Vdeo-club

- 15 -

Fernando Berzal

Paso 6: Mover el mtodo getPrecio()


Movemos la implementacin del mtodo getPrecio() de la clase
Alquiler al lugar que parece ms natural si los precios van ligados
a la pelcula que se alquila:

public class DVD


public double getPrecio (int tiempo)
{
double importe = 0;
switch (getTipo()) {
case DVD.NORMAL:
importe += 2;
if (tiempo>2)
importe += (tiempo-2) * 1.5;
break;
case DVD.NOVEDAD:
importe += tiempo * 3;
break;
case DVD.INFANTIL:
importe += 1.5;
if (tiempo>3)
importe += (tiempo-3) * 1.5;
break;
}
return importe;
}
public class Alquiler
public double getPrecio()
{
return _dvd.getPrecio(_tiempo);
}
OOP - Caso prctico: Vdeo-club

- 16 -

Fernando Berzal

Paso 7: Mover el mtodo getPuntos ()


Hacemos lo mismo con el mtodo getPuntos():

public class DVD


public int getPuntos (int tiempo)
{
int puntos = 1;
// Bonificacin
if ((getTipo() == DVD.NOVEDAD) && (tiempo>1))
puntos++;
return puntos;
}

public class Alquiler


public int getPuntos ()
{
return _dvd.getPuntos(_tiempo);
}

11/11
Como siempre, la ejecucin de los casos de prueba
nos confirma que todo funciona correctamente.
OOP - Caso prctico: Vdeo-club

- 17 -

Fernando Berzal

Paso 8: Reemplazar lgica condicional con polimorfismo


Queremos darle ms flexibilidad a la forma en la que se fijan los
precios de los alquileres de pelculas, para que se puedan aadir
nuevas categoras (por ejemplo, en la creacin de promociones) o
para que se puedan ajustar las tarifas:

NOTA:
Por qu no creamos una jerarqua de tipos de pelculas?

Porque las pelculas pueden cambiar de categora con el tiempo


(dejan de ser una novedad) pero siguen manteniendo su identidad.

OOP - Caso prctico: Vdeo-club

- 18 -

Fernando Berzal

Nos creamos la jerarqua correspondiente a las polticas de precios:

public abstract class Tarifa


{
public abstract int getTipo();
}

class TarifaNormal extends Tarifa


{
public int getTipo()
{
return DVD.NORMAL;
}
}

class TarifaInfantil extends Tarifa


{
public int getTipo()
{
return DVD.INFANTIL;
}
}

class TarifaEstreno extends Tarifa


{
public int getTipo()
{
return DVD.NOVEDAD;
}
}
OOP - Caso prctico: Vdeo-club

- 19 -

Fernando Berzal

A continuacin, en la clase DVD, sustituimos el atributo tipo por un


objeto de tipo Tarifa, en el cual recaer luego la responsabilidad de
establecer el precio correcto:

public class DVD


private String _titulo;
private Tarifa _tarifa;

public DVD (String titulo, int tipo)


{
_titulo = titulo;
setTipo(tipo);
}

public int getTipo()


{
return _tarifa.getTipo();
}

public void setTipo (int tipo)


{
switch (tipo) {
case DVD.NORMAL:
_tarifa = new TarifaNormal();
break;
case DVD.NOVEDAD:
_tarifa = new TarifaEstreno();
break;
case DVD.INFANTIL:
_tarifa = new TarifaInfantil();
break;
}
}

11/11
OOP - Caso prctico: Vdeo-club

- 20 -

Fernando Berzal

Finalmente, cambiamos la implementacin de getPrecio():


public abstract class Tarifa
public abstract double getPrecio (int tiempo);
class TarifaNormal extends Tarifa
public double getPrecio (int tiempo)
{
double importe = 2.0;
if (tiempo>2)
importe += (tiempo-2) * 1.5;
return importe;
}
class TarifaInfantil extends Tarifa
public double getPrecio (int tiempo)
{
double importe = 1.5;
if (tiempo>3)
importe += (tiempo-3) * 1.5;
return importe;
}
class TarifaEstreno extends Tarifa
public double getPrecio (int tiempo)
{
return tiempo * 3.0;
}

public class DVD


public double getPrecio (int tiempo)
{
return _tarifa.getPrecio(tiempo);
}

11/11
OOP - Caso prctico: Vdeo-club

- 21 -

Fernando Berzal

Paso 9: Reemplazar lgica condicional con polimorfismo II


Repetimos el mismo proceso de antes para el mtodo getPuntos():

public abstract class Tarifa


public int getPuntos (int tiempo)
{
return 1;
}

class TarifaNovedad extends Tarifa


public int getPuntos (int tiempo)
{
return (tiempo>1)? 2: 1;
}

public class DVD


public int getPuntos (int tiempo)
{
return _tarifa.getPuntos(tiempo);
}

OOP - Caso prctico: Vdeo-club

- 22 -

Fernando Berzal

Paso 10: Mejoras adicionales


Todava nos quedan algunas cosas que podramos mejorar

Las constantes simblicas definidas en la clase DVD son,


en realidad, meros identificadores que utilizamos para
las diferenciar las distintas polticas de precios, por lo
que deberamos pasarlas a la clase genrica Tarifa.

Podramos, directamente, eliminar esas constantes


artificiales y forzar que, al crear un objeto de tipo DVD,
el constructor reciba directamente como parmetro un
objeto de alguno de los tipos derivados de Tarifa (lo
que nos facilitara el trabajo enormemente si se
establecen nuevas polticas de precios).

Las distintas polticas de precios tienen caractersticas


en comn, por lo que podramos reorganizar la jerarqua
de clases teniendo en cuenta los rasgos comunes que se
utilizan para establecer los precios (esto es, el precio
base, el lmite de tiempo y la penalizacin por tiempo).

OOP - Caso prctico: Vdeo-club

- 23 -

Fernando Berzal

Clases y objetos
Relacin de ejercicios
1. Identifique los datos que decidira utilizar para almacenar el estado de los
siguientes objetos en funcin del contexto en el que se vayan a utilizar:
a. Un punto en el espacio.
b. Un segmento de recta.
c. Un polgono.
d. Una manzana (de las que se venden en un mercado).
e. Una carta (en Correos)
f. Un libro (en una biblioteca)
g. Un libro (en una librera)
h. Una cancin (en una aplicacin para un reproductor MP3).
i. Una cancin (en una emisora de radio)
j. Un disco de msica (en una tienda de msica).
k. Un disco de msica (en una discoteca).
l. Un telfono mvil (en una tienda de telefona)
m. Un telfono mvil (en el sistema de una empresa de telecomunicaciones)
n. Un ordenador (en una tienda de Informtica)
o. Un ordenador (en una red de ordenadores)
p. Un ordenador (en el inventario de una organizacin)
Declare las correspondientes clases en Java, defina los constructores que
considere adecuados e implemente los correspondientes mtodos para el acceso
y la modificacin del estado de los objetos (esto es, los mtodos get y set).

2. Cree una clase denominada Alarma cuyos objetos activen un objeto de tipo
Timbre cuando el valor medido por un Sensor supere un umbral
preestablecido:

Implemente en Java todo el cdigo necesario para el funcionamiento de la


alarma, suponiendo que la alarma comprueba si debe activar o desactivar el
timbre cuando se invoca el mtodo comprobar().
3. Cree una subclase de Alarma denominada AlarmaLuminosa que, adems de
activar el timbre, encienda una luz (que representaremos con un objeto de tipo
Bombilla).
NOTA: Procure eliminar la aparicin de cdigo duplicado al crear la subclase
de Alarma y asegrese de que, cuando se activa la alarma luminosa se
enciende la luz de alarma y tambin suena la seal sonora asociada al timbre.

4. Disee jerarquas de clases para representar los siguientes conjuntos de objetos:

a. Una coleccin de CDs, entre los cuales hay discos de msica (CDs de
audio), discos de msica en MP3 (CD-ROMs con msica), discos de
aplicaciones (CD-ROMs con software) y discos de datos (CD-ROMs con
datos y documentos).
b. Los diferentes productos que se pueden encontrar en una tienda de
electrnica, que tienen un conjunto de caractersticas comunes (precio,
cdigo de barras) y una serie de caractersticas especficas de cada
producto.
c. Los objetos de una coleccin de monedas/billetes/sellos.
Implemente en Java las jerarquas de clases que haya diseado (incluyendo sus
variables de instancia, sus constructores y sus mtodos get/set). A
continuacin, escriba sendos programas que realicen las siguientes tareas:
a. Buscar y mostrar todos los datos de un CD concreto (se recomienda
definir el mtodo toString en cada una de las subclases de CD).
b. Crear un carrito de la compra en el que se pueden incluir productos y
emitir un ticket en el que figuren los datos de cada producto del carrito,
incluyendo su precio y el importe total de la compra.
c. Un listado de todos los objetos coleccionables cuya descripcin incluya
una cadena de caracteres que el programa reciba como parmetro.

5. Implemente un programa que cree un objeto de la clase Random del paquete


java.util, genere un nmero entero aleatoriamente y lo muestre en pantalla.

6. Cree un paquete denominado documentos

a. Incluya en l dos clases, Factura y Pedido, para representar facturas y


pedidos, respectivamente.
b. A continuacin, ya fuera del paquete, cree un pequeo programa que
cree objetos de ambos tipos y los muestre por pantalla.
c. Aada un tercer tipo de documento, PedidoUrgente, que herede
directamente de Pedido. Compruebe que el programa anterior sigue
funcionando correctamente si reemplazamos un Pedido por un
PedidoUrgente.
d. Cree un nuevo tipo de documento, denominado Contrato, e inclyalo
en el subpaquete documentos.RRHH. En este ltimo paquete, incluya
tambin un tipo de documento CV para representar el currculum vitae de
una persona.
e. Si no lo ha hecho ya, cree una clase genrica Documento de la que
hereden (directa o indirectamente) todas las dems clases que hemos
definido para representar distintos tipos de documentos.
f.

Implemente un pequeo programa que cree un documento de un tipo


seleccionado por el usuario. Muestre por pantalla el documento
independientemente del tipo concreto de documento que se haya creado
en el paso anterior.

OBSERVACIONES:
Para cada clase que defina, determine qu miembros de la clase han de ser pblicos
(public), cules han de mantenerse privados (private) y, si lo considera
oportuno, cules seran miembros protegidos (protected).
Tenga en cuenta que no siempre se debe permitir la modificacin desde el exterior
de una variable de instancia (esto es, habr variables de instancia a las que
asociemos un mtodo get pero no un mtodo set y, de hacerlo, ste puede que sea
privado o protegido).
Analice tambin qu mtodos de una clase deben declararse con la palabra reservada
final para que no se puedan redefinir en subclases y qu clases han de ser finales
(esto es, aquellas clases de las que no queramos permitir que se creen subclases).
En los distintos programas de esta relacin de ejercicios puede resultar necesaria la
creacin de colecciones de objetos de distintos tipos (p.ej. arrays de CDs, productos,
objetos coleccionables o documentos).

Principios de
programacin orientada a objetos
Diseo de clases
Sntomas de un mal diseo
El principio de responsabilidad nica
El principio abierto-cerrado
El principio de sustitucin de Liskov
El principio de inversin de dependencias
Clases abstractas e interfaces
El principio de segregacin de interfaces
Ejemplo: Banca electrnica
Diseo de paquetes
Granularidad
Estabilidad

Bibliografa
Robert C. Martin:
Agile Software Development: Principles, Patterns, and Practices.
Prentice Hall, 2003. ISBN 0-13-597444-5.
http://www.objectmentor.com/resources

Diseo de clases
Cmo sabemos si nuestro diseo es correcto?
Existen algunos sntomas que nos indican
que el diseo de un sistema es bastante pobre:
- RIGIDEZ (las clases son difciles de cambiar)
- FRAGILIDAD (es fcil que las clases dejen de funcionar)
- INMOVILIDAD (las clases son difciles de reutilizar)
- VISCOSIDAD (resulta difcil usar las clases correctamente)
- COMPLEJIDAD INNECESARIA (sistema sobrediseado)
- REPETICIN INNECESARIA (abuso de copiar y pegar)
- OPACIDAD (aparente desorganizacin)

Afortunadamente, tambin existen algunos principios heursticos


que nos ayudan a eliminar los sntomas arriba enumerados:
Principio de responsabilidad nica
Principio abierto-cerrado
Principio de sustitucin de Liskov
Principio de inversin de dependencias
Principio de segregacin de interfaces

OOP Principios de diseo: Java

-1-

Fernando Berzal

Descripcin de los sntomas de un diseo mejorable


Rigidez
El sistema es difcil de cambiar porque cualquier cambio,
por simple que sea, fuerza otros muchos cambios en cascada.
Por qu es un problema?
Es ms complicado de lo que pens
Cuando nos dicen que realicemos un cambio, puede que nos
encontremos con que hay que hacer ms cosas de las que, en
principio, habamos pensado que haran falta.
Cuantos ms mdulos haya que tocar para hacer un cambio,
ms rgido es el sistema.
Fragilidad
Los cambios hacen que el sistema deje de funcionar
(incluso en lugares que, aparentemente,
no tienen nada que ver con lo que hemos tocado).
Por qu es un problema?
Porque la solucin de un problema genera nuevos problemas
Conforme la fragilidad de un sistema aumenta,
la probabilidad de que un cambio ocasione
nuevos quebraderos de cabeza tambin aumenta.
Inmovilidad
La reutilizacin de componentes requiere demasiado esfuerzo.
Por qu es un problema?
Porque la reutilizacin es siempre la solucin ms rpida.
Aunque un diseo incorpore elementos potencialmente tiles,
su inmovilidad hace que sea demasiado difcil extraerlos.
OOP Principios de diseo: Java

-2-

Fernando Berzal

Viscosidad
Es ms difcil utilizar correctamente lo que ya hay implementado
que hacerlo de forma incorrecta (e, incluso, que reimplementarlo).
Por qu es un problema?
Cuando hay varias formas de hacer algo, no siempre se elige
la mejor forma de hacerlo y el diseo tiende a degenerarse.
La alternativa ms evidente y fcil de realizar
ha de ser aqulla que preserve el estilo del diseo.
Complejidad innecesaria
El diseo contiene infraestructura que no proporciona beneficios.
Por qu es un problema?
A veces se anticipan cambios que luego no se producen, lo
que conduce a ms cdigo (que hay que depurar y mantener)
La complejidad innecesaria
hace que el software sea ms difcil de entender.
Repeticin innecesaria
Copiar y pegar resulta perjudicial a la larga.
Por qu es un problema?
Porque el mantenimiento puede convertirse en una pesadilla.
El cdigo duplicado debera unificarse bajo una nica abstraccin.
Opacidad
Cdigo enrevesado difcil de entender.
Por qu es un problema? Porque la entropa del cdigo
tiende a aumentar si no se toman las medidas oportunas.
Escribimos cdigo para que otros puedan leerlo (y entenderlo).
OOP Principios de diseo: Java

-3-

Fernando Berzal

El principio de responsabilidad nica


Tom DeMarco, 1979: Structured Analysis and System Specification

Una clase debe tener un nico motivo para cambiar.

Por ejemplo, podemos crear una clase Partida para representar una
partida de bolos (que consta de 10 jugadas):

La clase Partida tiene aqu dos responsabilidades diferentes:


- Mantener el estado actual de la partida (esto es, cuntos
lanzamientos llevamos realizados y cuntos nos quedan)
- Calcular nuestra puntuacin (siguiendo las reglas oficiales del
juego: 10 puntos por pleno [strike], etc.).
En una situacin as, puede interesarnos separar el clculo de la
puntuacin del mantenimiento del estado de la partida:

De esta forma, podramos utilizar nuestra clase Partida


para distintas variantes del juego (si es que existiesen) o
incluso para otros juegos (la petanca?).
OOP Principios de diseo: Java

-4-

Fernando Berzal

En este contexto,
una responsabilidad equivale a una razn para cambiar.
Si se puede pensar en ms de un motivo por el que cambiar una clase,
entonces la clase tiene ms de una responsabilidad.
Ejemplo
public class Modem
{
public void marcar (String nmero)
public void colgar ()
public void enviar (String datos)
public String recibir ()
}

La clase Modem tiene aqu dos responsabilidades:


- Encargarse de la gestin de las conexiones.
- Enviar y recibir datos.

Modem sigue teniendo dos responsabilidades y sigue siendo necesaria en


nuestra aplicacin, pero ahora nada depende de Modem:
Slo el programa principal ha de conocer la existencia de Modem.

Si la forma de hacerse cargo de una de las responsabilidades sabemos


que nunca vara, no hay necesidad de separarla
(se tratara de complejidad innecesaria en nuestro diseo):
Una razn de cambio slo es una razn de cambio
si el cambio llega a producirse realmente.
OOP Principios de diseo: Java

-5-

Fernando Berzal

El principio abierto-cerrado
Bertrand Meyer, 1997: Construccin de software orientado a objetos

Los mdulos deben ser a la vez abiertos y cerrados:


abiertos para ser extendidos y cerrados para ser usados.

1. Debe ser posible extender un mdulo para ampliar su conjunto de


operaciones y aadir nuevos atributos a sus estructuras de datos.
2. Un mdulo ha de tener un interfaz estable y bien definido (que no se
modificar para no afectar a otros mdulos que dependen de l).

Si se aplica correctamente este principio,


los cambios en un sistema se realizan siempre aadiendo cdigo, sin
tener que modificar la parte del cdigo que ya funciona.

El sencillo diseo siguiente no se ajusta al principio abierto-cerrado:

El Cliente usa los servicios de un Servidor concreto, al cual


est ligado. Si queremos cambiar el tipo de servidor, hemos de
cambiar el cdigo del cliente.

OOP Principios de diseo: Java

-6-

Fernando Berzal

Aunque pueda resultar paradjico, se puede cambiar lo que hace un


mdulo sin cambiar el mdulo: la clave es la abstraccin.

El siguiente diseo s se ajusta al principio abierto-cerrado:

InterfazCliente es una clase base utilizada por el cliente para

acceder a un servidor concreto: Los clientes acceden a servidores


concretos que implementen el interfaz definida por la clase
InterfazCliente.
Si queremos que un cliente utilice un servidor diferente, basta
con crear una clase nueva que tambin implemente la interfaz de
InterfazCliente (esto es, la clase Cliente no habr que
modificarla).
El trabajo que tenga que realizar el Cliente puede describirse
en funcin del interfaz genrico expuesto por
InterfazCliente, sin recurrir a detalles de servidores
concretos.
Por qu InterfazCliente y no ServidorGenrico?
Porque las clases abstractas (ms sobre ellas ms adelante)
estn ms ntimamente relacionadas a sus clientes
que a las clases concretas que las implementan.
OOP Principios de diseo: Java

-7-

Fernando Berzal

El principio abierto-cerrado
es clave en el diseo orientado a objetos.

Si nos ajustamos a l, obtenemos los mayores beneficios


que se suelen atribuir a la orientacin a objetos
(flexibilidad, mantenibilidad, reutilizacin).

No obstante,
pese a que la abstraccin y el polimorfismo lo hacen posible,
el principio abierto-cerrado
no se garantiza simplemente con utilizar
un lenguaje de programacin orientado a objetos.

De la misma forma,
tampoco tenemos que crear abstracciones arbitrariamente:
No todo tiene que ser abstracto:
El cdigo debe acabar haciendo algo concreto.
Las abstracciones se han de utilizar
en las zonas que exhiban cierta propensin a sufrir cambios.

OOP Principios de diseo: Java

-8-

Fernando Berzal

El principio de sustitucin de Liskov


Barbara Liskov: Data abstraction and hierarchy. SIGPLAN Notices, 1988

Los tipos base siempre se pueden sustituir por sus subtipos.

Si S es un subtipo de T,
cualquier programa definido en funcin de T
debe comportarse de la misma forma con objetos de tipo S.

OOP Principios de diseo: Java

-9-

Fernando Berzal

La importancia de este principio


se hace evidente cuando deja de cumplirse:

public class Figura


{

public void dibujar ()


{
if (this instanceof Polgono)
dibujarPolgono();
else if (this instanceof Crculo)
dibujarCrculo();
}

El mtodo dibujar viola el principio de sustitucin de Liskov, porque


ha de ser consciente de cualquier subtipo de Figura
que creemos en nuestro sistema
(p.ej. qu sucede si tambin tenemos que trabajar con elipses?).
De hecho, tambin se viola el principio abierto-cerrado.

La solucin: Utilizar polimorfismo


Cada tipo de figura ser responsable
de implementar el mtodo dibujar.

public class Polgono extends Figura

public void dibujar ()

public class Crculo extends Figura

public void dibujar ()

OOP Principios de diseo: Java

- 10 -

Fernando Berzal

Veamos un caso algo ms sutil:


Inicialmente trabajamos con rectngulos
public class Rentngulo
{
private double anchura;
private double altura;
public double getAnchura ()
public double getAltura ()
public void setAnchura ()
public void setAltura ()
}

Por lo que sea, tambin hemos de manipular cuadrados

La implementacin empieza a crear dificultades


public class Cuadrado extends Rentngulo
{
public void setAnchura (double x)
{
super.setAnchura(x);
super.setAltura(x);
}
public void setAltura (double x)
{
super.setAnchura(x);
super.setAltura(x);
}
}
OOP Principios de diseo: Java

- 11 -

Fernando Berzal

Ahora, consideremos el siguiente mtodo:

void f (Rectngulo rect)


{
rect.setAnchura(32);
}

Qu sucede si llamamos a este mtodo con un cuadrado?


La llamada a setAnchura
establece tambin la altura del rectngulo
(algo aparentemente correcto).

Pero, y si el mtodo hace algo diferente?

void g (Rectngulo rect)


{
rect.setAnchura(4);
rect.setAltura(5);
Assert.assertEquals( rect.getArea(), 20);
}

Obviamente, el cdigo anterior fallar


si el mtodo recibe un cuadrado en vez de un tringulo L

Por qu falla la implementacin?


Aunque el modelo del cuadrado como un tipo particular de rectngulo
parezca razonable, desde el punto de vista del programador del mtodo
g, un cuadrado no es un rectngulo!
Las relaciones de herencia se han de utilizar para heredar
comportamiento (el comportamiento que los clientes de una clase
pueden asumir y en el que confan).
OOP Principios de diseo: Java

- 12 -

Fernando Berzal

Formalmente,
la interfaz de una clase define su contrato.
El contrato se especifica declarando
las precondiciones y las postcondiciones asociadas a cada mtodo
(esto es, lo que verificamos con las pruebas de unidad con JUNIT):
Las precondiciones son las condiciones que
se han de cumplir antes de la llamada al mtodo.
Las postcondiciones son las condiciones que
se verifican tras la ejecucin del mtodo.

En el caso de la clase Rectngulo,


las postcondicin implcita de setAnchura es
(anchura == x) && (altura == old.altura)

donde old hace referencia al estado del rectngulo antes de la llamada.


Para la clase Cuadrado, no obstante,
la postcondicin asociada a setAnchura es
(anchura == x) && (altura == x)

Nuestra implementacin de setAnchura para la clase Cuadrado


es incorrecta porque impone un postcondicin distinta
a la impuesta por setAnchura en su clase base Rectngulo.

La redefinicin de un mtodo en una clase derivada slo puede


reemplazar la precondicin original por una ms dbil
y la postcondicin original por otra ms fuerte (restrictiva).

Por qu? Porque cuando se usa una clase base, slo se conocen las
precondiciones y postcondiciones asociadas a la clase base.
OOP Principios de diseo: Java

- 13 -

Fernando Berzal

El principio de inversin de dependencias


Robert C. Martin: C++Report, 1996

a) Los mdulos de alto nivel no deben depender de mdulos de


bajo nivel. Ambos deben depender de abstracciones.
b) Las abstracciones no deben depender de detalles. Los detalles
deben depender de las abstracciones.

La programacin estructurada
tiende a crear estructuras jerrquicas en las que
el comportamiento de los mdulos de alto nivel
(p.ej. el programa principal)
depende de detalles de mdulos de un nivel inferior
(p.ej. la opcin del men seleccionada por el usuario).

La estructura de dependencias en una aplicacin orientada a objetos


bien diseada suele ser la inversa.

Si se mantuviese la estructura tradicional:


Cuando se cambiasen los mdulos de nivel inferior,
habra que modificar los mdulos de nivel superior.
Adems, los mdulos de nivel superior resultaran difciles
de reutilizar si dependiesen de mdulos inferiores.

OOP Principios de diseo: Java

- 14 -

Fernando Berzal

Ejemplo
La inversin de dependencias de puede realizar siempre que una clase
enva un mensaje a otra y deseamos eliminar la dependencia

Tal como est diseado, no ser posible utilizar el botn para


encender, por ejemplo, un motor (ya que el botn depende
directamente de la lmpara que enciende y apaga).

Para solucionar el problema,


volvemos a hacer uso de nuestra capacidad de abstraccin:

Ahora podremos utilizar el botn


para cualquier cosa que se pueda encender y apagar.
OOP Principios de diseo: Java

- 15 -

Fernando Berzal

Clases abstractas e interfaces


Clases abstractas
Una clase abstracta
es una clase que no se puede instanciar
se usa nicamente para definir subclases

Cundo es una clase abstracta?


En cuanto uno de sus mtodos no tiene implementacin (en Java, el
mtodo abstracto se etiqueta con la palabra reservada abstract).

Cundo se utilizan clases abstractas?


Cuando deseamos definir una abstraccin que englobe objetos de
distintos tipos y queremos hacer uso del polimorfismo.

Figura es una clase abstracta (nombre en cursiva en UML)

porque no tiene sentido calcular su rea, pero s la de un cuadrado o un


crculo. Si una subclase de Figura no redefine area(), deber
declararse tambin como clase abstracta.
OOP Principios de diseo: Java

- 16 -

Fernando Berzal

public abstract class Figura


{
protected double x;
protected double y;
public Figura (double x, double y)
{
this.x = x;
this.y = y;
}
public abstract double area ();
}
public class Circulo extends Figura
{
private double radio;
public Circulo (double x, double y, double radio)
{
super(x,y);
this.radio = radio;
}
public double area ()
{
return Math.PI*radio*radio;
}
}
public class Cuadrado extends Figura
{
private double lado;
public Cuadrado (double x, double y, double lado)
{
super(x,y);
this.lado = lado;
}
public double area ()
{
return lado*lado;
}
}
OOP Principios de diseo: Java

- 17 -

Fernando Berzal

Interfaces
Una interfaz es una clase completamente abstracta
(una clase sin implementacin)

En el ejemplo anterior, si no estuvisemos interesados en conocer la


posicin de una Figura, podramos eliminar por completo su
implementacin y convertir Figura en una interfaz:

public interface Figura


{
public double area ();
}

En Java, las interfaces se declaran con la palabra reservada


interface de manera similar a como se declaran las clases
abstractas.
En la declaracin de una interfaz, lo nico que puede aparecer son
declaraciones de mtodos (su nombre y signatura, sin su
implementacin) y definiciones de constantes simblicas.
Una interfaz no encapsula datos, slo define cules son los mtodos
que han de implementar los objetos de aquellas clases que
implementen la interfaz.
OOP Principios de diseo: Java

- 18 -

Fernando Berzal

public class Circulo implements Figura


{
private double radio;
public Circulo (double radio)
{
this.radio = radio;
}
public double area ()
{
return Math.PI*radio*radio;
}
}

public class Cuadrado implements Figura


{
private double lado;
public Cuadrado (double lado)
{
this.lado = lado;
}
public double area ()
{
return lado*lado;
}
}

En Java, para indicar que una clase implementa una interfaz se


utiliza la palabra reservada implements.
La clase debe entonces implementar todos los mtodos definidos
por la interfaz o declararse, a su vez, como una clase abstracta (lo
que no suele ser especialmente til):
abstract class SinArea implements Figura
{
}
OOP Principios de diseo: Java

- 19 -

Fernando Berzal

Herencia mltiple de interfaces


Una clase puede implementar varios interfaces simultneamente,
pese a que, en Java, una clase slo puede heredar de otra clase
(herencia simple de implementacin, mltiple de interfaces).

public abstract class Figura


{
public abstract double area ();
}
public interface Dibujable
{
public void dibujar ();
}
public interface Rotable
{
public void rotar (double grados);
}
public class Circulo extends Figura
implements Dibujable

public class Cuadrado extends Figura


implements Dibujable, Rotable

OOP Principios de diseo: Java

- 20 -

Fernando Berzal

El principio de segregacin de interfaces


Robert C. Martin: C++Report, 1996

Los clientes de una clase


no deberan depender de interfaces que no utilizan.

PROBLEMA: Estamos implementando un sistema de seguridad en el


cual controlamos varias puertas. Algunas de esas puertas van
conectadas a un programa temporizador que las bloquea
automticamente pasado cierto tiempo:

Ahora bien, deseamos que el temporizador controle tambin otros


dispositivos (como una alarma que se dispara automticamente), por
lo que aplicamos el principio de inversin de dependencias:

OOP Principios de diseo: Java

- 21 -

Fernando Berzal

Como Java slo permite herencia simple (de implementacin),


hemos hecho que Puerta
herede de la clase abstracta ClienteTemporizador
para que PuertaTemporizada
pueda funcionar con un temporizador.
Como consecuencia,
todas las puertas, necesiten o no temporizador,
dependen del interfaz que utilizan los clientes de Temporizador.
Contaminacin de la interfaz:
Cuando se aade un mtodo a una clase base
simplemente porque una de sus clases derivadas lo necesita.
La interfaz de la clase base es ms compleja de lo que tiene que
ser, al incluir mtodos que no estn directamente relacionados
con ella [complejidad innecesaria]
Lo que se aade a la clase base tiene que estar disponible en
todas sus clases derivadas (y funcionar correctamente, si
queremos respetar el principio de sustitucin de Liskov).
Si tuvisemos que actualizar la interfaz que han de usar los
clientes de Temporizador, tendramos que modificar tambin la
implementacin de Puerta [fragilidad].
La clave:
Los clientes de un objeto de tipo T
no necesitan una referencia al objeto de tipo T para acceder a l:
basta con una referencia a uno de sus tipos base, o bien
una referencia a un objeto auxiliar que delegue las llamadas
necesarias en el objeto original de tipo T.

OOP Principios de diseo: Java

- 22 -

Fernando Berzal

Separacin por herencia mltiple


(cuando todas las clases base menos una son interfaces)

class PuertaTemporizada extends Puerta


implements ClienteTemporizador

Separacin por delegacin


(cuando habra que heredar simultneamente de varias clases)

class PuertaTemporizada extends Puerta

adaptador = new AdaptadorPT (this);


temporizador.registrar(adaptador);
OOP Principios de diseo: Java

- 23 -

Fernando Berzal

Ejemplo: Banca electrnica


Un sistema de banca electrnica debe tener varias interfaces de usuario
para que los clientes del banco puedan efectuar operaciones
(en un cajero automtico, por telfono y por Internet)

Sea cual sea el medio escogido,


el cliente ha de poder ejecutar varias transacciones:
Realizar depsitos (ingresar dinero en su cuenta).
Retirar efectivo (sacar dinero de su cuenta).
Realizar transferencias de dinero.
Consultar el saldo y los ltimos movimientos.
Recargar el mvil

OOP Principios de diseo: Java

- 24 -

Fernando Berzal

Solucin A
Interfaz contaminado

Cada tipo de transaccin utiliza algunos mtodos


que las dems transacciones no siempre utilizan
Un nuevo tipo de transaccin introducir cambios en
InterfazUsuario que afectarn al funcionamiento
de los dems tipos de transacciones.
OOP Principios de diseo: Java

- 25 -

Fernando Berzal

Solucin B
Adaptadores

OOP Principios de diseo: Java

- 26 -

Fernando Berzal

Solucin C
Segregacin de interfaces

OOP Principios de diseo: Java

- 27 -

Fernando Berzal

Diseo de paquetes
Conforme el tamao de las aplicaciones crece,
se hace necesario algn tipo de organizacin a alto nivel.
Las clases son unidades demasiado pequeas,
por lo que se agrupan en paquetes.
Qu criterios utilizaremos para organizar las clases?
Los mismos que para organizar los miembros de las clases:
la cohesin y el acoplamiento

Granularidad:
La cohesin de los paquetes
Cundo se ponen dos clases en el mismo paquete?
Cuando para usar una, siempre es necesario usar la otra.
Cuando dos clases estn en un mismo paquete,
es porque se usan juntas. Por tanto, todas las clases de un
paquete se usan conjuntamente: si se usa una, se usan todas.
A la inversa, cundo se ponen en paquetes diferentes?
Aqullas clases que no siempre se usen conjuntamente con las
dems clases del paquete son candidatas para abandonar el
paquete (quiz para ir a un subpaquete ms especfico).
Las clases de un paquete se vern afectadas por los mismos tipos de
cambios y las modificaciones necesarias para realizar un cambio
concreto debern estar localizadas en un nico paquete.
OOP Principios de diseo: Java

- 28 -

Fernando Berzal

Estabilidad:
El acoplamiento entre paquetes
Para facilitar el desarrollo de un sistemas complejo,
resulta aconsejable que las distintas partes del sistema
sean lo ms independientes posible:
Cuanto menos dependa un paquete de otros paquetes, mejor.

Un paquete es ms estable cuando depende de menos paquetes.


Cuando queramos que un paquete sea flexible (esto es, fcil de
cambiar), mejor si hay pocos paquetes que dependan de l.
Un paquete debe ser ms estable cuanto ms abstracto sea (un
paquete estable y concreto se vuelve rgido).
OOP Principios de diseo: Java

- 29 -

Fernando Berzal

Si dibujamos un diagrama con las dependencias existentes entre los


paquetes, el diagrama no debe tener ciclos:

Qu efectos ocasiona un ciclo?


Cuando trabajamos
en la construccin de la interfaz,
hemos de disponer de ciertos servicios
proporcionados por la aplicacin.
Esto hace que la interfaz dependa de todos los
dems paquetes de la aplicacin
Para probar el funcionamiento de la interfaz
necesitamos disponer de una implementacin
de todos los dems paquetes y las pruebas
dependern del estado actual de esos paquetes
(por lo que difcilmente se pueden considerar
pruebas de unidad).
OOP Principios de diseo: Java

- 30 -

Fernando Berzal

Cmo se rompe un ciclo entre dos paquetes?

1. Creando un nuevo paquete del que ambos dependan:

2. Aplicando el principio de inversin de dependencias:

OOP Principios de diseo: Java

- 31 -

Fernando Berzal

Caso prctico
Red de telefona mvil

Vamos a analizar la arquitectura software


de una red de telefona mvil de tercera generacin
UMTS (Universal Mobile Telecommunications System),

NOTA: La tecnologa UMTS sustituir a la tecnologa GSM


(Global System for Mobile Communications)

Material adaptado de
Michael Kircher & Prashant Jain:
Pattern-oriented Software Architecture
Volume 3: Patterns for Resource Management
John Wiley & Sons, 2004
ISBN 0-470-84525-2

Ilustraciones y figuras cortesa de


Michael Kircher (Siemens AG Corporate Technology, Munich)
OOP - Caso prctico: Red UMTS

-1-

Fernando Berzal

El funcionamiento de una red de telefona mvil

Generaciones de telfonos mviles


Generacin
Primera
Segunda
Tercera

Caractersticas
Transmisin analgica de voz
Transmisin digital de voz
Transmisin digital de voz y datos

Ejemplo
Moviline
GSM900
UMTS

Redes celulares de telefona mvil

Las frecuencias no se reutilizan en celdas adyacentes.


Para dar servicio a ms usuarios,
se utilizan celdas de menor tamao.

OOP - Caso prctico: Red UMTS

-2-

Fernando Berzal

Los elementos de una red de telefona mvil

1. Estaciones base (nodos B)


2. Controladores de la red de radio
(RNC: Radio Network Controller)
3. Centros de operacin y mantenimiento
(OMC: Operation and Maintenance Center)

Red

Controlador de
la red de radio

Centro de
operaciones y mantenimiento

Estacin base

Estacin base

Figura original cortesa de Michael Kircher

OOP - Caso prctico: Red UMTS

-3-

Fernando Berzal

Estaciones base
Se comunican con los telfonos mviles que hay en su celda
a travs de una o varias antenas.
Envan los datos que reciben de un telfono mvil al RNC,
que los reenva a otra estacin base (cuando el destinatario
es otro mvil) o a otra red (p.ej. red de telefona
convencional RTC).
Se reparten por amplias zonas geogrficas y han de ser muy
fiables para reducir su coste de mantenimiento (suelen tener
mltiples CPUs para ser capaces de procesar mltiples
llamadas en paralelo y evitar que el fallo de una CPU deje
inoperativa la estacin base)
RNCs
Hacen de mediadores entre las estaciones base y otras redes.
Son ordenadores potentes que suelen funcionar con sistemas
operativos convencionales.
OMC
Controla la configuracin del hardware y del software de las
estaciones base y de los RNCs.
Monitoriza el funcionamiento de la red y permite que
operadores humanos intervengan cuando sea necesario.
Es el nico elemento de la red que tiene interfaz de usuario.
Suele estar formado por un cluster de ordenadores (para
repartir la carga de trabajo entre varias mquinas y evitar
que el fallo de una de ellas inutilice el OMC).

OOP - Caso prctico: Red UMTS

-4-

Fernando Berzal

Establecimiento de una llamada con un telfono fijo:

Figura original cortesa de Michael Kircher

Cuando la seal que le llega de un telfono mvil a la estacin


base es demasiado dbil, el RNC se encarga de asignarle otra
estacin base ms cercana sin que se corte la conexin
(proceso conocido como call handover):

Figura original cortesa de Michael Kircher

OOP - Caso prctico: Red UMTS

-5-

Fernando Berzal

La arquitectura de una estacin base


El hardware de la estacin base

CPU
de operacin y
mantenimiento

CPUs
para el procesamiento
de llamadas
Estacin base

El software de la estacin base

OOP - Caso prctico: Red UMTS

-6-

Fernando Berzal

Unidad de procesamiento de llamadas


Establecimiento de conexiones (telfono mvil  RNC).
Gestin de conexiones entre CPUs de la estacin base.
Monitorizacin de las seales (p.ej. handover)

Unidad de operaciones y mantenimiento


representa todos los elementos de la estacin base como un rbol

Monitorizacin y configuracin de los elementos hardware


y software de la estacin base.
El rbol de elementos gestionados por la estacin base es
accesible remotamente desde el OMC para que el OMC
pueda controlar la estacin base.

OOP - Caso prctico: Red UMTS

-7-

Fernando Berzal

La arquitectura del centro de operaciones y mantenimiento


Administracin y monitorizacin de la red de telefona mvil
Funciones del OMC
Comunicacin con las estaciones base y los RNCs.
Descubrimiento de estaciones base.
Mantenimiento del estado de la red
(rbol topolgico completo de toda la red).
Configuracin de los elementos de la red.
Actualizacin del software de las estaciones base

RNC

Estacin
base

Estacin
base

CPU

Interfaz grfica de usuario para gestionar los elementos de la red

OOP - Caso prctico: Red UMTS

-8-

Fernando Berzal

Arquitectura del software del OMC

El patrn de diseo MVC


(Model-View-Controller = Modelo-Vista-Controlador)
El software del OMC est organizado segn el patrn MVC:
MODELO: El rbol topolgico mantiene informacin de
todos los elementos de la red.
VISTA: La interfaz de usuario permite la interaccin del
operador con los elementos de la red.
CONTROLADOR: El componente de gestin del rbol
topolgico se encarga de manipular el rbol y acceder a las
unidades de operaciones y mantenimiento de los elementos
de la red (estaciones base y RNCs).
NOTA: Los datos del estado de la red se almacenan localmente en
una base de datos por cuestiones de eficiencia (para no tener
que contactar con las estaciones base cada vez que queremos
algo, lo que introducira retardos que impediran el uso
cmodo de la interfaz de usuario).
OOP - Caso prctico: Red UMTS

-9-

Fernando Berzal

Para aprender ms sobre diseo orientado a objetos

OOP - Caso prctico: Red UMTS

- 10 -

Fernando Berzal

Programacin orientada a objetos


Relacin de ejercicios
1. En las jerarquas de clases que haya creado hasta ahora, analice detenidamente si
alguna de sus clases ha de ser abstracta. En particular, fjese en la existencia de
mtodos que no deberan implementarse en una clase base y habran de
declararse, por tanto, como mtodos abstractos. Alguna de las clases que
obtiene es completamente abstracta y debera convertirse en una interfaz?

2. Al estudiar clases y objetos, vimos cmo disear una alarma que conectbamos
a un sensor y activaba un timbre:

Si queramos que la alarma tambin encendiese una seal luminosa, lo que


hacamos era crear una subclase de Alarma. La herencia y el polimorfismo nos
permite crear distintos tipos de alarmas que comparten parte de su
comportamiento con la clase base Alarma. Ahora bien, si queremos aadir
nuevos dispositivos conectados a la alarma (p.ej. un telfono que
automticamente llama a la polica) y queremos que la alarma se pueda
configurar de forma flexible, se le ocurre alguna forma de hacerlo usando
interfaces? Implemente la solucin en Java.

3. Implemente en Java el sistema de seguridad asociado a una puerta con


temporizador, tal como se muestra en la siguiente figura:

4. Generalice el diseo anterior para que el temporizador pueda activar distintos


dispositivos aplicando el principio de segregacin de interfaces:
a. Usando herencia mltiple (de interfaces)

b. Usando delegacin (mediante un adaptador)

Implemente en Java todo el cdigo asociado a los dos diseos propuestos.


A continuacin, implemente en Java, utilizando las dos variantes descritas, el
cdigo necesario para que, por ejemplo, el temporizador cierre active
automticamente el sistema de riego del csped y, simultneamente, cierre las
persianas de la casa que dan al jardn

Clases y objetos
Ejercicio resuelto
Cree una clase denominada Alarma cuyos objetos activen un
objeto de tipo Timbre cuando el valor medido por un Sensor
supere un umbral preestablecido:

Implemente en Java todo el cdigo necesario para el


funcionamiento de la alarma, suponiendo que la alarma
comprueba si debe activar o desactivar el timbre
cuando se invoca el mtodo comprobar().

Cree una subclase de Alarma denominada AlarmaLuminosa


que, adems de activar el timbre, encienda una luz (que
representaremos con un objeto de tipo Bombilla).
NOTA: Procure eliminar la aparicin de cdigo duplicado
al crear la subclase de Alarma y asegrese de que,
cuando se activa la alarma luminosa, se enciende la luz
de alarma y tambin suena la seal sonora asociada al
timbre.

OOP Clases y objetos: Alarma

-1-

Fernando Berzal

/**
* Alarma
*/
public class Alarma
{
private Sensor sensor;
private Timbre timbre;
private double umbral;
/**
* Constructor
*/
public Alarma
(Sensor
{
this.sensor
this.timbre
this.umbral
}

sensor, Timbre timbre, double umbral)


= sensor;
= timbre;
= umbral;

/**
* Comprobar estado de la alarma
*/
public void comprobar ()
{
if (sensor.getValorActual()>umbral) {
timbre.activar();
} else {
timbre.desactivar();
}
}
}
OOP Clases y objetos: Alarma

-2-

Fernando Berzal

Programa principal:
public class Programa
{
// Programa principal
public static void main(String[] args)
{
SensorSwing sensor = new SensorSwing();
Timbre timbre = new Timbre();
Alarma alarma = new Alarma (sensor, timbre, 0.0);
sensor.setAlarma(alarma);
}
}
SensorSwing es un tipo particular de Sensor que se
encarga de llamar al mtodo comprobar() de la alarma

en cuanto se produce un cambio en el valor medido por el


sensor.

OOP Clases y objetos: Alarma

-3-

Fernando Berzal

Versin 1: Redefinicin del mtodo

comprobar()

public class Alarma


{
protected Sensor sensor;
protected Timbre timbre;
protected double umbral;
/**
* Constructor
*/
public Alarma
(Sensor sensor, Timbre timbre, double umbral)

/**
* Comprobar estado de la alarma
*/
public void comprobar ()
{
if (sensor.getValorActual()>umbral) {
timbre.activar();
} else {
timbre.desactivar();
}
}
}
OOP Clases y objetos: Alarma

-4-

Fernando Berzal

/**
* Alarma luminosa (versin 1)
*/
public class AlarmaLuminosa extends Alarma
{
private Bombilla bombilla;
/**
* Constructor
*/
public AlarmaLuminosa
( Sensor sensor, Timbre timbre,
Bombilla bombilla, double umbral)
{
super(sensor,timbre,umbral);
this.bombilla = bombilla;
}
/**
* Redefinicin del mtodo comprobar()
*/
public void comprobar ()
{
super.comprobar();
if (sensor.getValorActual()>umbral) {
bombilla.encender();
} else {
bombilla.apagar();
}
}
}

8 Acceso a miembros protegidos


(se rompe la encapsulacin de los objetos).
8 Existencia de cdigo duplicado (if...)
NOTA: Hemos de acordarnos de llamar al mtodo comprobar()
de la clase Alarma para que tambin suene el timbre.
OOP Clases y objetos: Alarma

-5-

Fernando Berzal

Versin 2: Uso correcto de la redefinicin de mtodos

La redefinicin de los mtodos activar() & desactivar()


nos permitir:
Reutilizar la lgica incluida en el mtodo comprobar()
sin tener que duplicar cdigo (la clase Alarma es la nica
responsable de la activacin de la alarma, hecho que
conllevar distintas consecuencias en funcin del tipo
particular de alarma).
Eliminar una posible fuente de errores (anteriormente, si
cambiasen las condiciones bajo las cuales se activa una
Alarma, tambin tendramos que revisar la implementacin
de comprobar() en la clase AlarmaLuminosa).
Mantener la encapsulacin de los objetos de la clase
Alarma (no se podr acceder a sus variables de instancia
desde el exterior de la clase)
OOP Clases y objetos: Alarma

-6-

Fernando Berzal

/**
* Alarma
*/
public class Alarma
{
private Sensor sensor;
private Timbre timbre;
private double umbral;
/**
* Constructor
*/
public Alarma
(Sensor sensor, Timbre timbre, double umbral)
{
this.sensor = sensor;
this.timbre = timbre;
this.umbral = umbral;
}
/**
* Comprobar estado de la alarma
*/
public final void comprobar ()
{
if (sensor.getValorActual()>umbral) {
activar();
} else {
desactivar();
}
}
public void activar ()
{
timbre.activar();
}
public void desactivar ()
{
timbre.desactivar();
}
}
OOP Clases y objetos: Alarma

-7-

Fernando Berzal

/**
* Alarma luminosa (versin 2)
*/
public class AlarmaLuminosa extends Alarma
{
private Bombilla bombilla;
/**
* Constructor
*/
public AlarmaLuminosa
( Sensor sensor, Timbre timbre,
Bombilla bombilla, double umbral)
{
super(sensor,timbre,umbral);
this.bombilla = bombilla;
}
/**
* Redefinicin del mtodo activar()
*/
public void activar ()
{
super.activar();
bombilla.encender();
}
/**
* Redefinicin del mtodo desactivar()
*/
public void desactivar ()
{
super.desactivar();
bombilla.apagar();
}
}

NOTA: Hemos de acordarnos de llamar a los mtodos correspondientes


de la clase Alarma para que el timbre siga sonando
OOP Clases y objetos: Alarma

-8-

Fernando Berzal

Apndice: Clases auxiliares


Una posible implementacin de sensores, timbres y bombillas

Sensor.java

/**
* Clase genrica para representar un sensor
*/
public class Sensor
{
/**
* Valor actual medido por el sensor
*/
private double valorActual;
/**
* Acceso al valor medido por el sensor
*/
public double getValorActual ()
{
return valorActual;
}
/**
* Modificacin del valor del sensor
* (algo de lo que se encargarn
* las subclases particulares de Sensor)
*/
protected void setValorActual (double valor)
{
valorActual = valor;
}
}

OOP Clases y objetos: Alarma

-9-

Fernando Berzal

SensorSwing.java
/**
* Sensor "ficticio"
* (demostracin del uso de SWING)
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SensorSwing extends Sensor
implements ActionListener
{
private JFrame
frame;
private JPanel
panel;
private JButton
button;
private JTextField editor;
private JLabel
info;
private Alarma

alarma;

/**
* Constructor
*/
public SensorSwing()
{
// Ventana (JFrame)
frame = new JFrame("Medidor de ");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300,100);
// Panel (JPanel)
// donde se colocan los controles de la interfaz
panel = new JPanel(new GridLayout(3, 1));
// Controles de la interfaz de usuario
// ----------------------------------editor = new JTextField(5);
info
= new JLabel("...", SwingConstants.CENTER);
button = new JButton("Actualizar");
OOP Clases y objetos: Alarma

- 10 -

Fernando Berzal

// Manejador de eventos asociado al botn


button.addActionListener(this);
// Colocar los controles en el panel
panel.add(editor);
panel.add(button);
panel.add(info);
// Botn por defecto
frame.getRootPane().setDefaultButton(button);
// Aadir el panel a la ventana
frame.getContentPane().add(panel);
// Mostrar la ventana
frame.setVisible(true);
}
/**
* Alarma asociada
*/
public void setAlarma (Alarma alarma)
{
this.alarma = alarma;
}
/**
* Pulsacin del botn.
*/
public void actionPerformed(ActionEvent event)
{
double valor = Double.parseDouble(editor.getText());
setValorActual(valor);
info.setText("Valor actual = " + valor);
if (alarma!=null) {
alarma.comprobar();
}
}
}
OOP Clases y objetos: Alarma

- 11 -

Fernando Berzal

Timbre.java
import java.awt.Toolkit;

/**
* Timbre
*/
public class Timbre
{
private static final int PITIDOS = 5;
/**
* Activar el timbre
*/
public void activar ()
{
int i;
for (i=0; i<PITIDOS; i++) {
Toolkit.getDefaultToolkit().beep();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
}
/**
* Desactivar el timbre
*/
public void desactivar ()
{
}
}

OOP Clases y objetos: Alarma

- 12 -

Fernando Berzal

Bombilla.java
Una ventana roja o verde en funcin del estado de la bombilla
import java.awt.*;
import javax.swing.*;
/**
* Bombilla
*/
public class Bombilla
{
private JFrame frame;
/**
* Constructor
*/
public Bombilla()
{
frame = new JFrame("Bombilla");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200,200);
frame.setVisible( true );
apagar();
}
/**
* Encender la bombilla
*/
public void encender ()
{
frame.getContentPane().setBackground( Color.red );
}
/**
* Apagar la bombilla
*/
public void apagar ()
{
frame.getContentPane().setBackground( Color.green );
}
}
OOP Clases y objetos: Alarma

- 13 -

Fernando Berzal

Excepciones
Qu es una excepcin?
Una situacin que, aunque puede pasar,
suele suponer algo negativo para la ejecucin de nuestro programa.

Ejemplos
El usuario escribe una palabra cuando se esperaba un nmero.
El programa intenta leer un fichero que no existe.
El programa no puede establecer una conexin de red.
Una conexin de red se pierde
El programa intenta realizar una divisin por cero.
Se intenta calcular la raz cuadrada de un nmero negativo.
El programa se sale de los lmites de un array.
El programa accede a los miembros de un objeto inexistente.

Terminologa
Cuando se produce una excepcin, la excepcin se lanza [throw].
Cuando se prev el posible lanzamiento de una excepcin y se toman
medidas al respecto en el cdigo de nuestra aplicacin, se captura la
excepcin [catch].
El manejo/tratamiento de excepciones consiste en capturar una
excepcin y tomar las medidas adecuadas al respecto.

Excepciones

-1-

Fernando Berzal

Gestin de errores
Qu hacer cuando se pueden producir errores

class EjemploSinControlDeErrores
{
public static void main(String args[])
{
mostrarEntero (args, 0);
}
public static void mostrarEntero
(String args[], int n)
{
System.out.println( "Entero: "
+ obtenerEntero(args,0) );
}
public static int obtenerEntero
(String args[], int n)
{
return Integer.parseInt(args[n]);
}
}

Idea inicial: Evitar los errores antes de que se produzcan


Aadir comprobaciones antes de operaciones peligrosas
No hacer nada que pueda fallar (algo imposible)

Por tanto, es necesario detectar cundo se produce un error


para tomar las medidas oportunas en cada momento

Excepciones

-2-

Fernando Berzal

Solucin 1: Cdigos de error


Aadir comprobaciones despus de operaciones falibles
Si se detecta algn error, devolver algn tipo de cdigo de error.

class EjemploConControlDeErrores
{
public static void main(String args[]) {
mostrarEntero (args, 0);
}
public static int mostrarEntero
(String args[], int n)
{
int
i
= obtenerEntero(args,n);
int
error = 0;
String salida = null;
if (i%2 == 0)
i = i/2;
else
error = -1; // Error en los argumentos
if (error == 0) {
if ( Runtime.getRuntime().freeMemory() > (8+10)*2 )
error = -2; // Memoria insuficiente
}
if (error == 0) {
salida = "Entero: " + i;
if (salida == null)
error = -3; // Error al crear la salida
}
if (error == 0) {
System.out.println(salida);
if (System.out.checkError())
error = -4; // Error al mostrar la salida
}
return error;
}
Excepciones

-3-

Fernando Berzal

public static int obtenerEntero


(String args[], int n)
{
int error = 0;
if (args == null || args.length == 0)
error = -1; // Vector inexistente
if (error == 0) {
if ((n<0) || (n>=args.length))
error = -3;
}
if (error == 0) {
if (!comprobarEntero(args[n]))
error = -5;
}
// Devuelve 2*entero, -1, -3 o -5
if (error == 0)
return 2*Integer.parseInt(args[n]);
else
return error;
}
public static boolean comprobarEntero
(String entero)
{
...
}
}

Inconvenientes
Demasiadas comprobaciones
Cdigo excesivamente enrevesado (confuso y propenso a errores)

Excepciones

-4-

Fernando Berzal

Solucin 2: Excepciones
Ya que los errores son inevitables,
las excepciones nos proporcionan una estructura de control que permite
implementar los casos normales con facilidad
y tratar separadamente los casos excepcionales

class EjemploConExcepciones
{
public static void main(String args[])
{
try {
mostrarEntero (args, 0);
} catch (Exception error) {
// Casos excepcionales...
}
}
// Casos normales...
public static void mostrarEntero
(String args[], int n)
{
System.out.println( "Entero: "
+ obtenerEntero(args,0) );
}
public static int obtenerEntero
(String args[], int n)
{
return Integer.parseInt(args[n]);
}
}

Adems, las excepciones nos permitirn mantener informacin acerca de


lo que fall (tipo de error, detalles relevantes y lugar en el que se produjo
el error) y enviar esta informacin al mtodo que queramos que se
encargue de tratar el problema, todo esto sin interferir con el
funcionamiento normal del programa (p.ej. sentencias return).
Excepciones

-5-

Fernando Berzal

Uso de excepciones en Java


En Java, cuando se produce un error en un mtodo,
se lanza un objeto Throwable.
Cualquier mtodo que haya llamado al mtodo puede capturar la
excepcin y tomar las medidas que estime oportunas.
Tras capturar la excepcin, el control no vuelve al mtodo en el que se
produjo la excepcin, sino que la ejecucin del programa contina en el
punto donde se haya capturado la excepcin.
Consecuencia:
Nunca ms tendremos que preocuparnos de disear cdigos de error.

Jerarqua de clases para el manejo de excepciones en Java

# $

!"

Excepciones

-6-

Fernando Berzal

Throwable
Clase base que representa todo lo que se puede lanzar en Java
Contiene una instantnea del estado de la pila en el momento en el
que se cre el objeto ( stack trace o call chain").
Almacena un mensaje (variable de instancia de tipo String)
que podemos utilizar para detallar qu error se produjo.
Puede tener una causa, tambin de tipo Throwable,
que permite representar el error que caus este error.

Error
Subclase de Throwable que indica problemas graves que una aplicacin
no debera intentar solucionar (documentacin de Java).
Ejemplos: Memoria agotada, error interno de la JVM

Exception
Exception y sus subclases indican situaciones que una aplicacin

debera tratar de forma razonable.


Los dos tipos principales de excepciones son:
RuntimeException (errores del programador, como una divisin

por cero o el acceso fuera de los lmites de un array)


IOException (errores que no puede evitar el programador,

generalmente relacionados con la entrada/salida del programa).

Excepciones

-7-

Fernando Berzal

Captura de excepciones: Bloques trycatch


Se utilizan en Java para capturar las excepciones que se hayan podido
producir en el bloque de cdigo delimitado por try y catch.
En cuanto se produce la excepcin, la ejecucin del bloque try termina.
La clusula catch recibe como argumento un objeto Throwable.

// Bloque 1
try {
// Bloque 2
} catch (Exception error) {
// Bloque 3
}
// Bloque 4

Sin excepciones:

124

Con una excepcin en el bloque 2:

1 2* 3 4

Con una excepcin en el bloque 1:

1*

// Bloque 1
try {
// Bloque 2
} catch (ArithmeticException ae) {
// Bloque 3
} catch (NullPointerException ne) {
// Bloque 4
}
// Bloque 5

Sin excepciones:

125

Excepcin de tipo aritmtico:

1 2* 3 5

Acceso a un objeto nulo (null):

1 2* 4 5

Excepcin de otro tipo diferente:

1 2*

Excepciones

-8-

Fernando Berzal

// Bloque1
try {
// Bloque 2
} catch (ArithmeticException ae) {
// Bloque 3
} catch (Exception error) {
// Bloque 4
}
// Bloque 5

Sin excepciones:

125

Excepcin de tipo aritmtico:

1 2* 3 5

Excepcin de otro tipo diferente:

1 2* 4 5

Ojo! Las clusulas check se comprueban en orden


// Bloque1
try {
// Bloque 2
} catch (Exception error) {
// Bloque 3
} catch (ArithmeticException ae) {
// Bloque 4
}
// Bloque 5

Sin excepciones:

125

Excepcin de tipo aritmtico:

1 2* 3 5

Excepcin de otro tipo diferente:

1 2* 3 5

El bloque 4 nunca se llegar a ejecutar !

Excepciones

-9-

Fernando Berzal

La clusula finally
En ocasiones, nos interesa ejecutar un fragmento de cdigo
independientemente de si se produce o no una excepcin
(por ejemplo, cerrar un fichero que estemos manipulando).

// Bloque1
try {
// Bloque 2
} catch (ArithmeticException ae) {
// Bloque 3
} finally {
// Bloque 4
}
// Bloque 5

Sin excepciones:

1245

Excepcin de tipo aritmtico:

1 2* 3 4 5

Excepcin de otro tipo diferente:

1 2* 4

Si el cuerpo del bloque try llega a comenzar su ejecucin,


el bloque finally siempre se ejecutar
Detrs del bloque try si no se producen excepciones
Despus de un bloque catch si ste captura la excepcin.
Justo despus de que se produzca la excepcin si ninguna clusula
catch captura la excepcin y antes de que la excepcin se
propague hacia arriba.

Excepciones

- 10 -

Fernando Berzal

Lanzamiento de excepciones
La sentencia throw
Se utiliza en Java para lanzar objetos de tipo Throwable
throw new Exception(Mensaje de error);

Cuando se lanza una excepcin:


Se sale inmediatamente del bloque de cdigo actual
Si el bloque tiene asociada una clusula catch adecuada para el
tipo de la excepcin generada, se ejecuta el cuerpo de la clusula
catch.
Si no, se sale inmediatamente del bloque (o mtodo) dentro del cual
est el bloque en el que se produjo la excepcin y se busca una
clusula catch apropiada.
El proceso contina hasta llegar al mtodo main de la aplicacin. Si
ah tampoco existe una clusula catch adecuada, la mquina
virtual Java finaliza su ejecucin con un mensaje de error.

Propagacin de excepciones (throws)


Si en el cuerpo de un mtodo se lanza una excepcin (de un tipo derivado
de la clase Exception), en la cabecera del mtodo hay que aadir una
clusula throws que incluye una lista de los tipos de excepciones que se
pueden producir al invocar el mtodo.
Ejemplo
public String leerFichero (String nombreFichero)
throws IOException
...

Las excepciones de tipo RuntimeException (que son muy comunes)


no es necesario declararlas en la clusula throws.
Excepciones

- 11 -

Fernando Berzal

Al implementar un mtodo, hay que decidir si las excepciones se


propagarn hacia arriba (throws) o se capturar en el propio mtodo
(catch)

1. Un mtodo que propaga una excepcin:

public void f() throws IOException


{
// Fragmento de cdigo que puede
// lanzar una excepcin de tipo IOException
}

NOTA: Un mtodo puede lanzar una excepcin porque cree


explcitamente un objeto Throwable y lo lance con throw, o bien
porque llame a un mtodo que genere la excepcin y no la capture.

2. Un mtodo equivalente que no propaga la excepcin:

public void f()


{
// Fragmento de cdigo libre de excepciones
try {
// Fragmento de cdigo que puede
// lanzar una excepcin de tipo IOException
// (p.ej. Acceso a un fichero)
} catch (IOException error) {
// Tratamiento de la excepcin
} finally {
// Liberar recursos (siempre se hace)
}
}

Excepciones

- 12 -

Fernando Berzal

Ejemplo clsico

public void transferir


(String IDorigen, String IDdestino, int cantidad)
{
Cuenta origen;
Cuenta destino;
// Comenzar transaccin
database.startTransaction();
try {
origen = database.find(IDorigen);
if (origen == null)
throw new Exception("No existe + IDorigen);
origen.setBalance (origen.getBalance() cantidad);
database.store(origen);
destino = database.find(IDdestino);
if (destino == null)
throw new Exception("No existe + IDdestino);
destino.setBalance(destino.getBalance()+cantidad);
database.store(destino)
// Confirmar la transaccin
database.commit();
} catch (Exception error) {
// Cancelar la transaccin
database.rollback();
}
}

Excepciones

- 13 -

Fernando Berzal

Creacin de nuevos tipos de excepciones


Un nuevo tipo de excepcin puede crearse fcilmente: basta con definir
una subclase de un tipo de excepcin ya existente.

public DivideByZeroException
extends ArithmeticException
{
public DivideByZeroException(String Message)
{
super(message);
}
}

Una excepcin de este tipo puede entonces lanzarse


como cualquier otra excepcin:

public double dividir(int num, int den)


throws DivideByZeroException
{
if (den==0)
throw new DivideByZeroException(Error!);
return ((double) num/(double)den);`
}

NOTA: Las aplicaciones suelen definir sus propias


subclases de la clase Exception para representar
situaciones excepcionales especficas de cada aplicacin.

Excepciones

- 14 -

Fernando Berzal

El sistema de E/S en Java:


Java:
Ficheros
Organizacin lgica de los datos
Ficheros y streams
La clase File
Streams de entrada: InputStream
Streams de salida: OutputStream
E/S de caracteres: Reader & Writer
Ficheros de texto
Creacin de un fichero de texto
Acceso secuencial al contenido de un fichero de texto
Serializacin de objetos
Serializacin
Deserializacin
Uso
Ficheros de acceso aleatorio

Organizacin de los datos


Sistemas basados en archivos
Campo

Unidad mnima (conjunto de bytes que


representa un dato, p.ej. cadena, fecha, nmero)

Registro

Conjunto de campos relacionados (p.ej. todos


los relacionados con una persona concreta).

Fichero

Conjunto de registros relacionados

Carpeta
/ Directorio

Conjunto de ficheros relacionados

Las carpetas o directorios se organizan jerrquicamente


(en carpetas y subcarpetas, directorios y subdirectorios)
para formar un rbol:

El sistema de E/S: Ficheros

-1-

Fernando Berzal

Ficheros y streams
Desde el punto de vista de Java,
cada fichero no es ms que una secuencia o flujo de bytes [stream].

Los streams pueden ser


de entrada (InputStream)
de salida (OutputStream).
Los ficheros pueden almacenar los datos
como secuencias de caracteres (ficheros de texto)
como secuencias de bytes (ficheros binarios)

Ejemplo: El nmero 5 se puede almacenar como el carcter


5 (cdigo ASCII 53, representado en UNICODE
mediante la secuencia de bits 0000 0000 0011 0101)
o bien como una secuencia de 32 bits en binario
(00000101)

Un programa en Java accede a un fichero creando un objeto asociado a


un stream del tipo adecuado (de entrada o de salida, de caracteres para
ficheros de texto o de bytes para ficheros binarios).
Los tipos ms comunes de streams estn definidos en el paquete
java.io de la biblioteca de clases estndar de Java.
Ejemplos: En nuestros programas ya hemos utilizado distintos streams
para leer datos desde el teclado y mostrar datos por pantalla:
System.out es un PrintStream
System.in es un InputStream

El sistema de E/S: Ficheros

-2-

Fernando Berzal

La clase File
Acceso a informacin acerca de ficheros y directorios:
import java.io.File;
import java.io.IOException;
import java.util.Date;
public class FileDemo
{
public void mostrarInfoFichero( String path )
throws IOException
{
File fichero = new File( path );
if ( fichero.exists() ) {
System.out.println("Nombre: "+fichero.getName());
System.out.println("- Ruta completa: "
+ fichero.getAbsolutePath() );
System.out.println("- Tamao: "
+ fichero.length() + " bytes");
System.out.println("- ltima modificacin: "
+ new Date(fichero.lastModified()) );
if (fichero.isFile()) {
System.out.println("- Fichero normal");
} else if (fichero.isDirectory()) {
System.out.println("- Directorio");
mostrarContenidoDirectorio(fichero);
}
} else {
throw new IOException
("El fichero '"+path+"' no existe");
}
}
public void mostrarContenidoDirectorio
(File directorio)
{
String ficheros[] = directorio.list();
for (int i=0; i<ficheros.length; i++)
System.out.println("\t"+ficheros[i]);
}
El sistema de E/S: Ficheros

-3-

Fernando Berzal

public static void main (String args[])


throws IOException
{
FileDemo demo = new FileDemo();
if (args.length>0) {
demo.mostrarInfoFichero(args[0]);
} else {
System.out.println ("USO:");
System.out.println ("java FileDemo <fichero>");
}
}
}

Fichero convencional
java FileDemo FileDemo.java
Nombre: FileDemo.java
- Ruta completa: F:\[fp]\ejemplos\FileDemo.java
- Tamao: 1496 bytes
- ltima modificacin: Thu Apr 28 16:31:23 CEST 2005
- Fichero normal

Directorio
java FileDemo f:\[fp]\ejemplos
Nombre: ejemplos
- Ruta completa: f:\[fp]\ejemplos
- Tamao: 0 bytes
- ltima modificacin: Thu Apr 28 16:31:05 CEST 2005
- Directorio
FileDemo.class
FileDemo.java

Fichero inexistente
java FileDemo xxx.java
Exception in thread "main" java.io.IOException:
El fichero 'xxx.java' no existe
at FileDemo.mostrarInfoFichero(FileDemo.java:40)
at FileDemo.main(FileDemo.java:59)

El sistema de E/S: Ficheros

-4-

Fernando Berzal

Streams de entrada
Las clases derivadas de InputStream representan flujos de datos de
entrada que pueden provenir de distintas fuentes:
Clase
ByteArray
InputStream
StringBuffer
InputStream
File
InputStream
Piped
InputStream
Sequence
InputStream

Fuente
de datos

Parmetros
del constructor

Array de bytes

Buffer del que leer los bytes

String

Cadena de caracteres

Fichero

Cadena con el nombre del


fichero u objeto de tipo File

Pipeline*

Piped
OutputStream

Otros
InputStreams

Secuencia de varios
InputStreams

Un pipeline se utiliza para enviar los datos de salida de


un programa directamente a la entrada de otro programa
(sin pasar por un fichero en disco)

Los tipos anteriores de InputStreams se utilizan como fuentes de


datos y se conectan luego a un FilterInputStream que nos permite
leer con mayor comodidad los datos de entrada.
FilterInputStream es una clase abstracta de la que derivan las

siguientes clases:
Clase
Data
InputStream
Buffered
InputStream
LineNumber
InputStream
Pushback
InputStream
El sistema de E/S: Ficheros

Funcin
Lectura de datos primitivos en binario
(int, char). Vase DataOutputStream
Usa un buffer para evitar el acceso a
disco cada vez que se lee un dato
Mantiene el nmero de lnea actual,
al que se accede con getLineNumber()
Permite devolver el ltimo byte ledo
-5-

Fernando Berzal

Streams de salida
Las clases derivadas de OutputStream permiten decidir a dnde
mandar los datos de salida:
Clase
ByteArray
OutputStream
File
OutputStream
Piped
InputStream

Destino
de los datos

Parmetros
del constructor

Array de bytes

Tamao inicial del buffer

Fichero

Cadena con el nombre del


fichero u objeto de tipo File

Pipeline*

Piped
InputStream

Un pipeline se utiliza para enviar los datos de salida de


un programa directamente a la entrada de otro programa
(sin pasar por un fichero en disco)

Los tipos anteriores de OutputStreams


se conectan a un FilterOutputStream
que facilita generar la salida en el formato adecuado.
FilterOutputStream es una clase abstracta

de la que derivan las siguientes clases:

Clase
Data
OutputStream
PrintStream
Buffered
OutputStream

El sistema de E/S: Ficheros

Funcin
Salida de datos primitivos en binario.
Vase DataInputStream
Salida con formato
(p.ej. System.out)
Salida a travs de un buffer.
El mtodo flush() permite vaciarlo.

-6-

Fernando Berzal

Lectores y escritores: Readers & Writers


Ficheros de texto en Java (E/S de caracteres)

Subclases de Reader
Clase

Fuente

Buffered
Reader

Reader

CharArray
Reader

char[]

FileReader

Fichero

InputStream
Reader
LineNumber
Reader
Piped
Reader
String
Reader

InputStream

Uso
Aade un buffer
del que leer los caracteres
Lectura de caracteres a partir
de un array de caracteres
Lectura de caracteres
de un fichero de texto
Convierte un InputStream
en un Reader

Reader

Mantiene el nmero de lnea

Pipeline*

PipedWriter

String

Lectura de caracteres
de una cadena

Subclases de Writer
Clase

Destino

Buffered
Writer

Reader

CharArray
Writer

char[]

FileWriter

Fichero

OutputStream
Writer
Piped
Writer

OutputStream

Uso
Aade un buffer
en el que escribir caracteres
Escritura de caracteres
en un array de caracteres
Escritura de caracteres
en un fichero de texto
Conecta un Writer
con un OutputStream

Pipeline*

PipedReader

PrintWriter

OutputStream

Salida con formato en un

String
Writer

String

El sistema de E/S: Ficheros

-7-

OutputStream

Escritura de caracteres
en una cadena
Fernando Berzal

Configuraciones tpicas
Leer datos desde el teclado con System.in

import java.io.*;
public class TestSystemIn
{
public static void main (String[] args)
throws IOException
{
InputStreamReader reader;
BufferedReader
input;
// Secuencia de bytes -> Secuencia de caracteres
reader = new InputStreamReader(System.in);
// Secuencia de caracteres -> Secuencia de lneas
input = new BufferedReader(reader);
// Lectura de una lnea de texto
System.out.println("Escriba algo...");
String cadena = input.readLine();
System.out.println("Ha escrito: "+cadena);
}
}

El sistema de E/S: Ficheros

-8-

Fernando Berzal

Configuraciones tpicas
Mostrar el contenido de un fichero
Solucin 1: Byte a byte

import java.io.*;
public class TestReadByte
{
public static void main(String[] args)
throws IOException
{
FileInputStream
file;
BufferedInputStream buffered;
DataInputStream
in;
// Apertura del fichero (modo de lectura)
file = new FileInputStream(args[0]);
// con buffer
buffered = new BufferedInputStream(file);
// para leer datos en binario
in = new DataInputStream(buffered);

// Recorrido secuencial del fichero


while (in.available() != 0)
System.out.print((char)in.readByte());

// Cierre del fichero


in.close();
}
}
El sistema de E/S: Ficheros

-9-

Fernando Berzal

Configuraciones tpicas
Mostrar el contenido de un fichero
Solucin 2: Lnea a lnea

import java.io.*;
public class TestReadLine
{
public static void main(String[] args)
throws IOException
{
FileReader
file;
BufferedReader in;
String
cadena;
// Apertura del fichero de texto (modo de lectura)
file = new FileReader(args[0]);
// con buffer para leer lnea a lnea
in = new BufferedReader(file);

// Lectura del fichero lnea a lnea


cadena = in.readLine();
while (cadena!=null) {
System.out.println(cadena);
cadena = in.readLine();
}
// Cierre del fichero
in.close();
}
}

El sistema de E/S: Ficheros

- 10 -

Fernando Berzal

Caso prctico: Agenda


Vamos a trabajar con los datos de una agenda de contactos:
import java.util.Date;
public class Contacto
{
private String nombre;
private String telfono;
private String email;
private String direccin;
private Date
nacimiento;
private int
grupo;
private double deuda;
// Constantes simblicas
public static final int TRABAJO = 1;
public static final int FAMILIA = 2;
public static final int AMIGOS = 3;
// Constructor
public Contacto (String nombre)
{
this.nombre = nombre;
}
// Mtodos set & get
...
// Salida estndar
public String toString ()
{
return nombre + "(" + email + ")\n"
+ " Telfono: "+ telefono + "\n"
+ " Cumpleaos: "+ nacimiento + "\n"

+ " Deuda: "+ deuda + "
}
}

El sistema de E/S: Ficheros

- 11 -

Fernando Berzal

Ficheros de texto
Ejemplos de uso de ficheros de acceso secuencial

Fernando
958 24 05 99
fberzal@decsai.ugr.es
CCIA - Despacho 17
3 de diciembre de 1977
1
6.6
Juan Carlos
958 24 05 97
JC.Cubero@decsai.ugr.es
CCIA - Despacho 37
29 de enero de 1962
1
-6.6

Fichero de texto clientes.txt


con los datos de dos contactos de nuestra agenda

Creacin de un fichero de texto


ContactoWriter salida;
...
salida = new ContactoWriter();
salida.abrir();
salida.escribir( contacto1 );
salida.escribir( contacto2 );
salida.cerrar();
El sistema de E/S: Ficheros

- 12 -

Fernando Berzal

import java.io.*;
import java.util.Date;
import java.text.DateFormat;
public class ContactoWriter
{
private FileWriter
writer;
private BufferedWriter buffer;
private PrintWriter
output;
// Apertura del fichero de texto
public void abrir()
throws IOException
{
try {
writer = new FileWriter( "clientes.txt" );
buffer = new BufferedWriter(writer);
output = new PrintWriter(writer);
} catch (SecurityException securityException) {
System.err.println
("No tiene permiso para escribir en el fichero");
throw securityException;
} catch (FileNotFoundException fileException) {
System.err.println
("Error al crear el fichero" );
throw fileException;
}
}
// Cierre del fichero de texto
public void cerrar()
throws IOException
{
if ( output != null )
output.close();
}
El sistema de E/S: Ficheros

- 13 -

Fernando Berzal

// Escribir los datos de un contacto en el fichero


public void escribir (Contacto contacto)
{
DateFormat df;
String
str;
df = DateFormat.getDateInstance(DateFormat.LONG);
if (contacto!=null) {
output.println(contacto.getNombre());
output.println(contacto.getTelefono());
output.println(contacto.getEmail());
output.println(contacto.getDireccion());
str = df.format(contacto.getNacimiento());
output.println(str);
output.println(contacto.getGrupo());
output.println(contacto.getDeuda());
}
}
}

El fichero ha de estar abierto para escribir datos en l.


Si queremos modificar un fichero de texto, tendremos que
reescribirlo por completo (en un fichero auxiliar para no perder los
datos si la operacin falla.
Cada llamada al mtodo escribir(contacto) le aade al fichero
de texto 7 lneas con los datos de contacto de una persona:
Fernando
958 24 05 99
fberzal@decsai.ugr.es
CCIA - Despacho 17
3 de diciembre de 1977
1
6.6
El sistema de E/S: Ficheros

- 14 -

Fernando Berzal

Acceso al contenido de un fichero de texto


El siguiente programa lee secuencialmente los datos almacenados en
el fichero de texto creado con la clase ContactoWriter:

import java.io.IOException;
import java.util.Date;
public class LeerContactos
{
public static void main( String args[] )
throws IOException, java.text.ParseException
{
Contacto
contacto;
ContactoReader entrada;
// Lectura de datos
entrada = new ContactoReader();
entrada.abrir();
do {
contacto = entrada.leer();
System.out.println(contacto);
} while (contacto!=null);
entrada.cerrar();
}
}

La clase auxiliar ContactoReader nos permite ir leyendo los


datos de los contactos en el mismo orden en el que estn en el
fichero (acceso secuencial).
Los ficheros de texto tienen la ventaja de que podemos leerlos
fcilmente con cualquier otro programa y modificarlos a mano.
Los ficheros de texto tienen el inconveniente de que su
manipulacin selectiva es difcil (su actualizacin, por ejemplo,
suele requerir volver a escribir el fichero completo).
El sistema de E/S: Ficheros

- 15 -

Fernando Berzal

import java.io.*;
import java.util.Date;
import java.text.DateFormat;

public class ContactoReader


{
private FileReader
reader;
private BufferedReader input;
// Abpertura del fichero de texto
public void abrir()
throws IOException
{
try {
reader = new FileReader( "clientes.txt" );
input = new BufferedReader(reader);
} catch (SecurityException securityException) {
System.err.println
("No tiene permiso para leer el fichero");
throw securityException;
} catch (FileNotFoundException fileException) {
System.err.println
("Error al acceder al fichero");
throw fileNotFoundException;
}
}
// Cierre del fichero de texto
public void cerrar()
throws IOException
{
if ( input != null )
input.close();
}

El sistema de E/S: Ficheros

- 16 -

Fernando Berzal

// Lectura de datos del fichero de texto


public Contacto leer ()
throws IOException,
NumberFormatException,
java.text.ParseException
{
Contacto
contacto = null;
Date
fecha;
DateFormat df;
int
grupo;
double
deuda;
String
str;
df = DateFormat.getDateInstance(DateFormat.LONG);
str = input.readLine();
if (str!=null) {
contacto = new Contacto (str);
contacto.setTelefono (input.readLine());
contacto.setEmail (input.readLine());
contacto.setDireccion (input.readLine());
fecha = df.parse(input.readLine());
contacto.setNacimiento (fecha);
grupo = Integer.parseInt(input.readLine());
contacto.setGrupo(grupo);
deuda = Double.parseDouble(input.readLine());
contacto.setDeuda(deuda);
}
return contacto;
}
}

El sistema de E/S: Ficheros

- 17 -

Fernando Berzal

Serializacin de objetos
Java facilita el almacenamiento y transmisin del estado de un objeto
mediante un mecanismo conocido con el nombre de serializacin.
La serializacin de un objeto consiste en generar una secuencia de
bytes lista para su almacenamiento o transmisin. Despus, mediante
la deserializacin, el estado original del objeto se puede reconstruir.
Para que un objeto sea serializable, ha de implementar la interfaz
java.io.Serializable (que lo nico que hace es marcar el objeto
como serializable, sin que tengamos que implementar ningn mtodo).

import java.io.Serializable;
import java.util.Date;
public class Contacto implements Serializable
{
private String nombre;
private String telefono;
private String email;
private String direccion;
private Date
nacimiento;
private int
grupo;
private double deuda;

Para que un objeto sea serializable, todas sus variables de


instancia han de ser serializables.
Todos los tipos primitivos en Java son serializables por defecto
(igual que los arrays y otros muchos tipos estndar).

El sistema de E/S: Ficheros

- 18 -

Fernando Berzal

Serializacin
import java.io.*;

public class ContactoOutput


{
private FileOutputStream
file;
private ObjectOutputStream output;
// Abrir el fichero
public void abrir()
throws IOException
{
file = new FileOutputStream( "clientes.ser" );
output = new ObjectOutputStream(file);
}
// Cerrar el fichero
public void cerrar()
throws IOException
{
if (output!=null)
output.close();
}
// Escribir en el fichero
public void escribir (Contacto contacto)
throws IOException
{
if (output!=null)
output.writeObject(contacto);
}
}

El sistema de E/S: Ficheros

- 19 -

Fernando Berzal

Deserializacin
import java.io.*;
public class ContactoInput
{
private FileInputStream
file;
private ObjectInputStream input;
public void abrir()
throws IOException
{
file = new FileInputStream( "clientes.ser" );
input = new ObjectInputStream (file);
}
public void cerrar()
throws IOException
{
if (input!=null )
input.close();
}

public Contacto leer ()


throws IOException, ClassNotFoundException
{
Contacto
contacto = null;
if (input!=null) {
try {
contacto = (Contacto) input.readObject();
} catch (EOFException eof) {
// Fin del fichero
}
}
return contacto;
}
}

El sistema de E/S: Ficheros

- 20 -

Fernando Berzal

Uso
Escritura de datos
ContactoOutput salida;
salida = new ContactoOutput();
salida.abrir();
salida.escribir( contacto1 );
salida.escribir( contacto2 );
salida.cerrar();

Lectura de datos
Contacto
ContactoInput

contacto;
entrada;

entrada = new ContactoInput();


entrada.abrir();
do {
contacto = entrada.leer();
System.out.println(contacto);
} while (contacto!=null);
entrada.cerrar();

NOTA: El fichero con los objetos serializados contactos.ser


almacena los datos en un formato propio de Java, por lo que no se
puede leer fcilmente con un simple editor de texto (ni editar).

El sistema de E/S: Ficheros

- 21 -

Fernando Berzal

Ficheros de acceso aleatorio


Los ficheros con los que hemos trabajado hasta ahora (ya sean ficheros
de texto o ficheros binarios con objetos serializados) no resultan
adecuados para muchas aplicaciones en las que hay que trabajar
eficientemente con un subconjunto de los datos almacenados en disco.

En este tipo de aplicaciones, se ha de acceder a un registro concreto


dentro de un fichero, por lo que los registros deben ser de tamao fijo:

Campo
Nombre
Telfono
E-Mail
Direccin
Fecha de nacimiento
Grupo
Deuda
TOTAL

Contenido
32 caracteres
16 caracteres
32 caracteres
64 caracteres
32 caracteres
1 int
1 double

Tamao
64 bytes
32 bytes
64 bytes
128 bytes
64 bytes
4 bytes
8 bytes
364 bytes

Como Java utiliza caracteres UNICODE, cada carcter de una


cadena de caracteres ocupa 16 bits (2 bytes).
La clase RandomAccessFile nos permitir representar un
fichero de acceso aleatorio para el que nosotros definiremos el
formato de sus registros.

El sistema de E/S: Ficheros

- 22 -

Fernando Berzal

Registro
import java.io.*;
import java.text.DateFormat;

public class Registro extends Contacto


{
public final static int DIM = 364;
// Lectura
public void read (RandomAccessFile file)
throws IOException, java.text.ParseException
{
DateFormat df;
setNombre
setTelefono
setEmail
setDireccion

(
(
(
(

readString
readString
readString
readString

(file,
(file,
(file,
(file,

32)
16)
32)
64)

);
);
);
);

df = DateFormat.getDateInstance(DateFormat.LONG);
setNacimiento ( df.parse(readString(file,32)) );
setGrupo(file.readInt());
setDeuda(file.readDouble());
}

private String readString


(RandomAccessFile file, int dim)
throws IOException
{
char campo[] = new char[dim];
for (int i=0; i<dim; i++)
campo[i] = file.readChar();
return new String(campo).replace('\0',' ');
}
El sistema de E/S: Ficheros

- 23 -

Fernando Berzal

// Escritura
public void write (RandomAccessFile file)
throws IOException
{
DateFormat df;
writeString
writeString
writeString
writeString

(file,
(file,
(file,
(file,

getNombre(),
getTelefono(),
getEmail(),
getDireccion(),

32);
16);
32);
64);

df = DateFormat.getDateInstance(DateFormat.LONG);
writeString (file, df.format(getNacimiento()), 32);
file.writeInt
( getGrupo() );
file.writeDouble ( getDeuda() );
}

private void writeString


(RandomAccessFile file, String str, int dim)
throws IOException
{
StringBuffer buffer = new StringBuffer();
if (str!=null)
buffer.append(str);
buffer.setLength(dim);
file.writeChars(buffer.toString());
}
}

El sistema de E/S: Ficheros

- 24 -

Fernando Berzal

Fichero de contactos
import java.io.*;

public class Contactos


{
// Fichero de acceso aleatorio
private RandomAccessFile file;

// Apertura del fichero


public void abrir()
throws IOException
{
file = new RandomAccessFile("clientes.dat","rw");
}

// Cierre del fichero


public void cerrar()
throws IOException
{
if (file!=null)
file.close();
}

// Escribir un registro
// en la posicin actual del cursor
public void escribir (Registro registro)
throws IOException
{
if (file!=null)
registro.write(file);
}

El sistema de E/S: Ficheros

- 25 -

Fernando Berzal

// Escribir un registro en una posicin cualquiera


public void escribir (Registro registro, int pos)
throws IOException
{
if (file!=null) {
file.seek ( (pos-1)*Registro.DIM );
escribir(registro);
}
}
// Leer del fichero el registro
// que se encuentra en la posicin actual del cursor
public Registro leer ()
{
Registro registro = null;
if (file!=null) {
try {
registro = new Registro();
registro.read(file);
} catch (Exception error) {
registro = null;
}
}
return registro;
}
// Leer del fichero un registro cualquierta
// (el parmetro indica la posicin del registro)
public Registro leer (int pos)
throws IOException
{
if (file!=null) {
file.seek ( (pos-1)*Registro.DIM );
}
return leer();
}
}
El sistema de E/S: Ficheros

- 26 -

Fernando Berzal

Ejemplos de uso
Registro contacto;
Contactos agenda;
agenda = new Contactos();

Escritura secuencial de datos


agenda.abrir();
agenda.escribir( contacto1 );
agenda.escribir( contacto2 );
...
agenda.cerrar();

Lectura secuencial del fichero


agenda.abrir();
do {
contacto = agenda.leer();
...
} while (contacto!=null);
agenda.cerrar();

Acceso aleatorio a los datos (lectura y actualizacin)


agenda.abrir();
contacto = agenda.leer(2);
contacto.setNombre("JC");
agenda.escribir(contacto,2);
agenda.cerrar();

El sistema de E/S: Ficheros

- 27 -

Fernando Berzal

Interfaces grficas de usuario


La mayor parte de las aplicaciones que se utilizan hoy en da incluyen
interfaces de usuario ms sofisticadas que las de las aplicaciones que
se ejecutan en modo consola.
Java incluye, como parte de su biblioteca de clases estndar, un
conjunto de componentes para crear interfaces grficas de usuario.
Siguiendo la filosofa de su lema (write once, run anywhere), estos
componentes permiten crear interfaces portables.

AWT y Swing
Los componentes que se utilizan en Java para crear interfaces grficas
de usuario se agrupan en dos paquetes (y sus correspondientes
subpaquetes):
java.awt (Abstract Window Toolkit)

Los componentes AWT dependen de las facilidades grficas


ofrecidas por cada sistema operativo: los programas escritos con
AWT tendrn un look and feel distinto en Windows y en
UNIX.
javax.swing

SWING es 100% Java y, por tanto, completamente


independiente de la plataforma: los componentes grficos se
pintan en tiempo de ejecucin (por lo que las aplicaciones
SWING suelen ser algo ms lentas que las AWT).
En la prctica, las aplicaciones Java con interfaces grficas de usuario
suelen mezclar AWT y SWING (porque AWT se encarga de toda la
gestin de eventos y SWING ofrece componentes ms sofisticados).
Interfaces de usuario

-1-

Fernando Berzal

Frames
Los frames (marcos) son ventanas en las que se pueden colocar otros
controles de los que se utilizan para crear las interfaces grficas de
usuario (botones, etiquetas, cajas de texto, listas desplegables, mens,
etctera).
AWT

SWING

java.awt.Frame

javax.swing.JFrame

import javax.swing.*;
class PrimerFrame extends JFrame
{
public PrimerFrame()
{
setTitle("Mi primer programa grfico");
setSize(400,100);
}
}
public class FrameTest
{
public static void main(String[] args)
{
JFrame frame = new PrimerFrame();
frame.setVisible(true);
}
}

NOTA: Por defecto, un frame es de tamao 0 x 0 pxeles.


Interfaces de usuario

-2-

Fernando Berzal

Eventos
El programa anterior tiene un problema:
Cuando se cierra la ventana,
dejamos de verla pero el programa no finaliza su ejecucin.

Para que el programa funcione correctamente, hemos de interceptar el


evento que se produce cuando cerramos la ventana y hacer que el
programa termine su ejecucin en ese momento.
Para ello, hay que definir un manejador de eventos en el cul
especificamos qu es lo que queremos que haga el programa.
WindowListener & WindowAdapter
En este caso, hemos de definir un WindowListener (clase encargada
de escuchar eventos asociados a ventanas) y asocirselo al Jrame de
nuestro ejemplo.
La interfaz java.awt.event.indowListener incluye 7 mtodos
que corresponden a las distintas acciones que podemos realizar sobre
una ventana:
traerla a primer plano (windowActivated),
dejarla en segundo plano (windowDeactivated),
minimizarla (windowIconified),
restaurarla (windowDeiconified),
abrirla (windowOpened)
o cerrarla (windowClosed y windowClosing)
Para que no tengamos que definir los 7 mtodos, AWT incluye una
clase auxiliar, llamada WindowAdapter, de la que slo tenemos que
redefinir aqullos mtodos que verdaderamente nos interesen.

Interfaces de usuario

-3-

Fernando Berzal

import javax.swing.*;
import java.awt.event.*;
class PrimerFrame extends JFrame
{
public PrimerFrame()
{
setTitle("Mi primer programa grfico");
setSize(400,100);
addWindowListener(new PrimerWindowListener());
}
}
class PrimerWindowListener extends WindowAdapter
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}

public class FrameTestExit


{
public static void main(String[] args)
{
JFrame frame = new PrimerFrame();
frame.setVisible(true);
}
}

Interfaces de usuario

-4-

Fernando Berzal

Componentes Swing

Las clases cuyo nombre comienza por J forman parte de Swing.


Todas las dems estn incluidas en AWT (Abstract Window Toolkit)
Component es una clase abstracta que representa a cualquier

componente con representacin grfica.


Container es un componente que puede contener a otros
componentes grficos (p.ej. JPanel).
JFrame permite representar ventanas, si bien tambin se pueden
utilizar clases como JApplet o JDialog.
Interfaces de usuario

-5-

Fernando Berzal

Componentes estndar
Los frames (como JFrame) son contenedores, por lo que incluyen un
panel de contenido (content pane) al cual se le pueden aadir
componentes grficos (etiquetas, botones, cajas de texto, etc.) y otros
contenedores (como paneles JPanel).
Las interfaces grficas de usuario se construyen con componentes,
cada uno de los cuales est preparado para responder a distintos tipos
de eventos. Algunos de los componentes incluidos en Swing son:
JLabel (etiqueta para mostrar texto)
JTextBox & JTextArea (cajas de texto para la entrada de datos)
JButton (botn)
JCheckBox (caja de comprobacin, para elegir opciones)
JRadioButton (para elegir opciones mutuamente excluyentes)
JList (lista de opciones)
JComboBox (lista desplegable de opciones)
JScrollBar (barra de scroll)
JTree (rbol)
JTable (tabla)

Mens: JMenuBar, JMenu, JMenuItem


Ventanas de dilogo: JOptionPane
Ventanas estndar: JFileChooser, JColorChooser
Interfaces de usuario

-6-

Fernando Berzal

Distribucin del espacio (layout management)


Antes de construir una interfaz grfica de usuario es importante saber
cmo se distribuyen especialmente los componentes.
Los layout managers controlan la forma en la que colocan los
componentes dentro de un contenedor:
FlowLayout (por defecto para un JPanel) coloca los

componentes de izquierda a derecha, de arriba abajo. Los


componentes se van colocando a la derecha de los ya existentes
hasta que se aade una nueva fila cuando no queda espacio
suficiente en la fila actual. Cuando el contenedor se
redimensiona, los componentes se redistribuyen
automticamente.
BorderLayout (por defecto para un JFrame) permite dividir el

espacio disponible de la siguiente forma:

NORTH
WEST

CENTER

EAST

SOUTH
Usualmente,
al JFrame se le aaden paneles usando BorderLayout
y luego se rellenan los paneles JPanel usando FlowLayout

Existen otros layout managers ms sofisticados (como GridLayout o


GridBagLayout) e incluso podemos crear nuestros propios gestores
de layout si implementamos las interfaces java.awt.LayoutManager
y java.awt.LayoutManager2.

Interfaces de usuario

-7-

Fernando Berzal

Dibujo de grficos 2D
Los paneles (como JFrame) son contenedores que pueden contener
otros componentes y, adems, tienen una superficie sobre la que se
puede dibujar (canvas o lienzo).
Para dibujar en un panel JPanel, hay que redefinir el mtodo
paintComponent() de la clase JComponent, que se invoca
automticamente cada vez que hay que refrescar la visualizacin del
componente en la pantalla (p.ej. cuando se mueve o redimensiona una
ventana).
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class JPanelFrame extends JFrame
{
public JPanelFrame()
{
this.setTitle("Mi primer programa grfico");
this.setSize(400,150);
this.addWindowListener(new MainWindowListener());
this.getContentPane().add(new MiPanel());
}
}
class MainWindowListener extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
public class JPanelTest
{
public static void main(String[] args)
{
JFrame frame = new JPanelFrame();
frame.setVisible(true);
}
}
Interfaces de usuario

-8-

Fernando Berzal

class MiPanel extends JPanel


{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
// Figuras geomtricas
g.setColor(Color.RED);
g.drawRect(20,20,360,60);
g.setColor(Color.CYAN);
int[] xcoords={25,35,365,375,375,25};
int[] ycoords={35,25, 25, 35, 75,75};
g.drawPolygon(xcoords,ycoords,6);
g.fillPolygon(xcoords,ycoords,6);
g.setColor(Color.LIGHT_GRAY);
g.drawOval(100,30,90,60);
g.fillOval(100,30,90,60);
// Mensaje de texto
Font f = new Font("Helvetica",Font.BOLD,25);
g.setFont(f);
g.setColor(Color.WHITE);
g.drawString("Hola!",250,60);
g.setColor(Color.BLACK);
g.drawString("Hola!",248,58);
}
}

Un objeto de tipo java.awt.Graphics define


el contexto en el que se dibuja (tipo de letra, estilo de lnea, color),
e incluye mtodos para dibujar distintos tipos de figuras
y mostrar mensajes de texto.
Interfaces de usuario

-9-

Fernando Berzal

Visualizacin de imgenes
El mtodo Graphics.drawImage()
nos permite dibujar imgenes en formato GIF, PNF o JPEG.
Las imgenes podemos leerlas con el mtodo getImage()
de la clase java.awt.Toolkit

class ImagePanel extends JPanel


{
Image img;
public ImagePanel ()
{
img=Toolkit.getDefaultToolkit().getImage("java.jpg");
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if (img!=null)
g.drawImage(img,0,0,this);
}
}
Interfaces de usuario

- 10 -

Fernando Berzal

El resto del cdigo es igual que en los ejemplos anteriores:


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class ImageFrame extends JFrame


{
public ImageFrame()
{
setTitle("Mi visor de imgenes...");
setSize(600,440);
addWindowListener(new MainWindowListener());
Container contenido = getContentPane();
contenido.add(new ImagePanel());
}
}

class MainWindowListener extends WindowAdapter


{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}

public class ImageTest


{
public static void main(String[] args)
{
JFrame frame = new ImageFrame();
frame.setVisible(true);
}
}

Interfaces de usuario

- 11 -

Fernando Berzal

Manejo de eventos AWT


En las aplicaciones en modo consola, nuestro mtodo main determina
el orden en el que se ejecutan las operaciones de nuestro programa.
En las aplicaciones con interfaces grficas de usuario, el orden en el
que se ejecutan las operaciones depender de las acciones del usuario.
Nosotros slo hemos de preocuparnos de qu acciones ha de realizar
nuestra aplicacin, cundo han de realizarse y definir los
correspondientes manejadores de eventos, que sern invocados
automticamente cuando sus eventos asociados se produzcan.

El modelo de eventos de Java


Cada lenguaje de programacin tiene su propio modelo de eventos:
En Visual Basic, cada componente genera eventos especficos y
nosotros redefinimos la respuesta del componente a cada evento
(modelo simple pero bastante inflexible).
En C, todos los eventos se sitan en una cola: hemos de ir
leyendo los eventos de esta cola y decidir qu accin realizar en
funcin del evento extrado de la cola (tedioso de programar).
En Java, se definen clases auxiliares (event listeners) que pueden
recibir eventos de tipos especficos (p.ej. el clic del botn del
ratn). Estas clases se asocian luego a componentes especficos.
o A diferencia de VB,
el manejador no viene predeterminado (mayor flexibilidad).
o A diferencia de C,
cada tipo de evento se puede tratar por separado.
Interfaces de usuario

- 12 -

Fernando Berzal

En trminos de objetos y mtodos,


el manejo de eventos en Java funciona de la siguiente forma:
Los manejadores de eventos (event listeners) se registran en las
distintas fuente de eventos (event source).
Una fuente de eventos (el ratn, un botn, una ventana) enva
objetos de tipo EventObject a todos los manejadores
registrados cuando se produce un nuevo evento.
Cada manejador de eventos utiliza la informacin recibida a
travs del objeto de tipo EventObject para realizar las acciones
que estime adecuadas.

En Java, los eventos estn organizados en una jerarqua de clases


dentro del paquete java.awt.event
La clase java.util.EventObject es la clase base de todos los
eventos en Java.
La subclase java.awt.AWTEvent es la clase base de todos los
eventos que se utilizan en la construccin de GUIs.
Cada tipo de evento XxxEvent tiene asociada una interfaz
XxxListener que es la que nos permite definir manejadores de
eventos.
Para simplificar la implementacin de algunos manejadores de
eventos, el paquete java.awt.event incluye clases base
XxxAdapter que implementan las interfaces XxxListener
Por ejemplo, para gestionar los eventos del ratn usaremos
MouseAdapter, para controlar los eventos de una ventana
recurriremos a WindowAdapter y para especificar lo que har nuestra
aplicacin cuando se pulse un botn emplearemos ActionListener.
Interfaces de usuario

- 13 -

Fernando Berzal

Ejemplo: Botones & ActionListener


Una aplicacin que nos permita cambiar el color del fondo

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class EventFrame extends JFrame
{
public EventFrame()
{
setTitle("Demostracin del uso de eventos...");
setSize(600,440);
addWindowListener(new MainWindowListener());
Container contenido = getContentPane();
contenido.add(new ButtonPanel());
}
}
class MainWindowListener extends WindowAdapter
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}
public class EventTest
{
public static void main(String[] args)
{
JFrame frame = new EventFrame();
frame.setVisible(true);
}
}
Interfaces de usuario

- 14 -

Fernando Berzal

class ButtonPanel extends JPanel


implements ActionListener
{
private JButton redButton;
private JButton greenButton;
private JButton blueButton;
public ButtonPanel()
{
redButton = new JButton("Rojo");
greenButton = new JButton("Verde");
blueButton = new JButton("Azul");
this.add(redButton);
this.add(greenButton);
this.add(blueButton);
redButton.addActionListener(this);
greenButton.addActionListener(this);
blueButton.addActionListener(this);
}
public void actionPerformed (ActionEvent event)
{
Object source = event.getSource();
Color color = getBackground();
if (source == redButton)
color = Color.RED;
else if (source == greenButton)
color = Color.GREEN;
else if (source == blueButton)
color = Color.BLUE;
setBackground(color);
repaint();
}
}

Interfaces de usuario

- 15 -

Fernando Berzal

Ejemplo: El ratn & MouseAdapter


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MouseTest
{
public static void main(String[] args)
{
JFrame frame = new MouseFrame();
frame.setVisible(true);
}
}
class MouseFrame extends JFrame
{
public JLabel info;
public MouseFrame()
{
setTitle("Demostracin del uso de eventos...");
setSize(600,440);
addWindowListener(new MainWindowListener());
info = new JLabel("Juegue con el ratn");
Container contenido = getContentPane();
contenido.add(info, BorderLayout.SOUTH);
this.addMouseListener
(new MiMouseAdapter(this));
this.addMouseMotionListener
(new MiMouseMotionAdapter(this));
}
}
class MainWindowListener extends WindowAdapter
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}
Interfaces de usuario

- 16 -

Fernando Berzal

class MiMouseAdapter extends MouseAdapter


{
private MouseFrame frame;
public MiMouseAdapter (MouseFrame frame)
{ this.frame = frame; }
public void mouseClicked (MouseEvent event)
{
frame.info.setText ("Ratn pulsado en ("
+ event.getX() + "," + event.getY() + ")");
}
public void mouseEntered (MouseEvent event)
{
frame.info.setText ("El ratn entr en la ventana");
}
public void mouseExited (MouseEvent event)
{
frame.info.setText ("El ratn sali de la ventana");
}
}
class MiMouseMotionAdapter extends MouseMotionAdapter
{
private MouseFrame frame;
public MiMouseMotionAdapter (MouseFrame frame)
{ this.frame = frame; }
public void mouseMoved (MouseEvent event)
{
frame.info.setText ("Ratn en ("
+ event.getX() + "," + event.getY() + ")");
}
}
Interfaces de usuario

- 17 -

Fernando Berzal

Ejemplo: Uso de otros componentes Swing

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class ListFrame extends JFrame
implements ActionListener
{
JPanel
tools;
JComboBox font;
JComboBox fontsize;
JCheckBox bold;
JCheckBox italic;
FontPanel panel;
public ListFrame()
{
setTitle("Demostracin del uso de eventos...");
setSize(600,150);
addWindowListener(new MainWindowListener());
// Barra de herramientas
tools = new JPanel();
tools.add(new JLabel("Fuente "));
font = new JComboBox();
font.setEditable(false);
font.addItem("Serif");
font.addItem("SansSerif");
font.addItem("Monospaced");
font.addActionListener(this);
tools.add(font);
Interfaces de usuario

- 18 -

Fernando Berzal

tools.add(new JLabel("Tamao "));


fontsize = new JComboBox();
fontsize.setEditable(true);
fontsize.addItem("12");
fontsize.addItem("16");
fontsize.addItem("24");
fontsize.addActionListener(this);
tools.add(fontsize);
bold = new JCheckBox("Negrita");
bold.addActionListener(this);
tools.add(bold);
italic= new JCheckBox("Cursiva");
italic.addActionListener(this);
tools.add(italic);
getContentPane().add(tools, "South");
panel = new FontPanel();
getContentPane().add(panel, "Center");
}
public void actionPerformed(ActionEvent event)
{
String tipo
= (String)font.getSelectedItem();
String str
= (String)fontsize.getSelectedItem();
int
dim
= Integer.valueOf(str).intValue();
int
estilo = (bold.isSelected()? Font.BOLD: 0)
+ (italic.isSelected()? Font.ITALIC: 0);
panel.setFont(tipo, estilo, dim);
repaint();
}
}
class MainWindowListener extends WindowAdapter
{
public void windowClosing (WindowEvent e)
{
System.exit(0);
}
}
Interfaces de usuario

- 19 -

Fernando Berzal

class FontPanel extends JPanel


{
private Font font;
public void setFont (String font, int style, int size)
{
this.font = new Font ( font, style, size);
}
public void paintComponent (Graphics g)
{
if (font!=null)
g.setFont(font);
g.drawString("Texto del panel", 50,50);
}
}

public class JListTest


{
public static void main(String[] args)
{
JFrame frame = new ListFrame();
frame.setVisible(true);
}
}

Interfaces de usuario

- 20 -

Fernando Berzal

Applets
Los applets son aplicaciones Java que se ejecutan dentro de un
navegador web (generalmente, como parte de una pgina web).

Ejemplo
En vez de partir de JFrame, usamos JApplet:

import java.awt.*;
import javax.swing.*;
class DemoPanel extends JPanel
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setFont(new Font("SansSerif",Font.BOLD,36));
g.drawString("Hola a todos!", 50, 120);
}
}
public class DemoJApplet extends JApplet
{
public void init()
{
Container contentPane = getContentPane();
contentPane.add(new DemoPanel());
}
}

El applet comenzar su ejecucin en el mtodo init(), si bien


antes hemos de incluirlo dentro de una pgina web (un fichero de
texto en formato HTML).

Interfaces de usuario

- 21 -

Fernando Berzal

<HTML>
<HEAD>
<TITLE>Applet de ejemplo</TITLE>
<META NAME="Author" CONTENT="Fernando Berzal">
</HEAD>
<BODY>
<H1>Applet Java</H1>
<APPLET CODE="DemoJApplet.class" WIDTH=300 HEIGHT=300>
</APPLET>
</BODY>
</HTML>

Al abrir la pgina con nuestro navegador se obtendr algo similar a lo


siguiente:

Interfaces de usuario

- 22 -

Fernando Berzal

Applets con parmetros


La pgina HTML
<HTML>
<HEAD>
<TITLE>Applet con parmetos</TITLE>
</HEAD>
<BODY BGCOLOR="WHITE">
<H1>Un applet con parmetros</H1>
<P>
<APPLET CODE="Message.class" WIDTH=325 HEIGHT=25>
<PARAM NAME="MESSAGE" VALUE="Un mensaje">
<B>Esta pgina necesita Java</B>
</APPLET>
<P>
<APPLET CODE="Message.class" WIDTH=325 HEIGHT=50>
<PARAM NAME="MESSAGE" VALUE="Otro mensaje">
<B>Esta pgina necesita Java</B>
</APPLET>
</BODY>
</HTML>

En la etiqueta <APPLET> se incluyen:


Los atributos WIDTH y HEIGHT para establecer las
dimensiones del applet (en pxeles).
Etiquetas <PARAM> para pasarle parmetros al applet.
Un fragmento de HTML que se mostrar nicamente si nuestro
navegador no soporta applets Java:
<B>Esta pgina necesita Java</B>
Interfaces de usuario

- 23 -

Fernando Berzal

El fichero de cdigo Java


import java.applet.Applet;
import java.awt.*;
public class Message extends Applet
{
private int fontSize;
private String message;
public void init() {
setBackground(Color.BLACK);
setForeground(Color.WHITE);
fontSize = getSize().height - 10;
setFont(new Font("SansSerif", Font.BOLD, fontSize));
message = getParameter("MESSAGE");
}
public void paint(Graphics g) {
if (message != null)
g.drawString(message, 5, fontSize+5);
}
}

El resultado

Interfaces de usuario

- 24 -

Fernando Berzal

Conversin de una aplicacin en un applet


Esencialmente, un applet es un contenedor (como JFrame), por lo que
nos basta con reemplazar el JFrame correspondiente a la ventana
principal de nuestra aplicacin por un componente JApplet.
Slo hay que tener en cuenta las siguientes diferencias:
El tamao del applet en pantalla viene determinado por los
atributos WIDTH y HEIGHT asociados a la etiqueta <APPLET> en
la pgina web que aloja el applet.
El applet, a diferencia de un JFrame, no tiene barra de ttulo,
sino que aparece en el interior de una pgina web (la cual puede
tener cualquier caracterstica que deseemos).
Para crear un applet no hace falta un mtodo main(). Nos basta
con definir el mtodo init() del applet.
Por motivos de seguridad, determinadas operaciones no se
pueden realizar desde un applet (como borrar ficheros del disco
duro, ejecutar otros programas o conectarse con mquinas
distintas de la mquina en la que se aloja la pgina con el applet)
salvo que firmemos el applet.

Interfaces de usuario

- 25 -

Fernando Berzal

Concurrencia
Procesos y hebras
Concurrencia
Programacin concurrente
Por qu usar hebras y procesos?
Ejecucin de procesos
Ejecucin de hebras
Hebras vs. Procesos
Creacin y ejecucin de hebras
La prioridad de las hebras
Finalizacin de la ejecucin de una hebra
Uso de recursos compartidos
Mecanismos de exclusin mutua
synchronized

Hebras e interfaces de usuario


SwingUtilities.invokeLater()
javax.swing.Timer

Ms informacin

Procesos y hebras
Hoy en da, cualquier usuario espera poder hacer varias cosas a la
vez y no verse forzado a ejecutar los programas secuencialmente.
Los sistemas operativos multitarea, como Windows o UNIX,
se encargan de que varios programas se puedan ejecutar a la vez
(concurrentemente) incluso cuando slo se dispone de una nica
CPU.

Concurrencia
Dos tareas se dice que son concurrentes si transcurren durante el
mismo intervalo de tiempo.
Se entiende por programacin concurrente el conjunto de
tcnicas y notaciones que sirven para expresar el paralelismo
potencial en los programas, as como resolver problemas de
comunicacin y sincronizacin.
Cuando se trabaja en entornos distribuidos o con mquinas con
mltiples procesadores, se suele hablar de programacin
distribuida o paralela, respectivamente.

NOTA:

En un PC, el sistema operativo pasa el control de la


CPU de una tarea a otra cada pocos milisegundos, algo
conocido como cambio de contexto.
Al realizar los cambios de contexto en intervalos de
tiempo muy cortos, el usuario tiene la percepcin de
que las distintas tareas se ejecutan en paralelo (algo
que, obviamente, slo sucede si disponemos de un
multiprocesador o de un multicomputador).

Concurrencia

-1-

Fernando Berzal

Cuando decidimos descomponemos un programa en varias tareas


potencialmente paralelas, estas tareas las podemos implementar
en el ordenador como procesos o como hebras:

Un PROCESO es un programa en ejecucin


con un estado asociado.
o Las distintas aplicaciones que se pueden ejecutar en un
sistema operativo multitarea son procesos independientes.
o Cada proceso ocupa un espacio de memoria independiente
(para no interferir con la ejecucin de otros procesos).
o Una aplicacin puede implementarse como un conjunto de
procesos que colaboren entre s para lograr sus objetivos,
para lo que se pueden emplear distintos mecanismos de
comunicacin entre procesos.

Los sistemas operativos actuales permiten un nivel adicional de


paralelismo dentro de un proceso: En un proceso pueden existir
varias HEBRAS de control independientes [threads].
o Cada hebra es una va simultnea de ejecucin dentro del
espacio de memoria del proceso.
o La comunicacin entre las distintas hebras se puede realizar
a travs del espacio de memoria que comparten, aunque
habr que utilizar mecanismos de sincronizacin para
controlar el acceso a este recurso compartido por todas las
hebras de un proceso.

Se denomina APLICACIN CONCURRENTE a una aplicacin que se


descompone en un conjunto de procesos y/o hebras. Del mismo
modo, una APLICACIN MULTIHEBRA est constituida por distintas
hebras que comparten el espacio de memoria de un proceso.
Concurrencia

-2-

Fernando Berzal

Programacin concurrente
Independientemente de si utilizamos procesos o hebras, el
desarrollo de aplicaciones concurrentes involucra el uso de
tcnicas especficas y la superacin de dificultades que no se
presentan en la implementacin de programas secuenciales.
A la hora de crear aplicaciones concurrentes, distribuidas o
paralelas, deberemos tener en mente ciertas consideraciones:
El diseo de aplicaciones concurrentes es ms complejo que
el de aplicaciones secuenciales, ya que hemos de
descomponer el programa en un conjunto de tareas con el
fin de aprovechar el paralelismo que pueda existir. Si no
existe ese paralelismo potencial, no tiene sentido que
intentemos descomponer nuestra aplicacin en tareas
independientes.
La implementacin de aplicaciones concurrentes es
tambin ms compleja que la de aplicaciones secuenciales
convencionales porque hemos de garantizar la coordinacin
de las distintas hebras o procesos.
La depuracin de las aplicaciones concurrentes es
extremadamente difcil, dado que la ejecucin de los
distintos procesos/hebras se entrelaza conforme el sistema
operativo les va asignando la CPU (algo que no podemos
prever por completo).
En tiempo de ejecucin, adems, cada hebra o proceso
supone una carga adicional para el sistema, por lo hay que
tener en cuenta la eficiencia de la implementacin
resultante. Deberemos ser cuidadosos para asegurar que se
aprovecha el paralelismo para mejorar el rendimiento de la
aplicacin. Este rendimiento puede medirse en funcin del
tiempo de respuesta del sistema o de la cantidad de trabajo
que realiza por unidad de tiempo [throughput].
Concurrencia

-3-

Fernando Berzal

Por qu usar hebras y procesos?


El no determinismo introducido por el entrelazado de las
operaciones de las distintas hebras o procesos de una aplicacin
concurrente provoca la aparicin de errores difciles de detectar y
ms an de corregir: la vida del programador resultara mucho
ms sencilla si no hiciese falta la concurrencia.
Sin embargo, existen razonas por las cuales es aconsejable utilizar
procesos y hebras:

1. De cara al usuario
Hebras y procesos permiten la creacin de interfaces que
respondan mejor a las rdenes del usuario.

Cuando una aplicacin tiene que realizar alguna tarea larga, su


interfaz debera seguir respondiendo
o La ventana de la aplicacin debera refrescarse y no
quedarse en blanco (como pasa demasiado a menudo).
o Los botones existentes para cancelar una operacin
deberan cancelar la operacin de un modo inmediato
(y no al cabo de un rato, cuando la operacin ya ha
terminado de todos modos).

Si nuestra aplicacin ha de atender las peticiones de distintos


usuarios (como sucede, por ejemplo, en un servidor web), el uso
de hebras o procesos permite que varios usuarios accedan
simultneamente a la aplicacin sin tener que esperar turno.

Concurrencia

-4-

Fernando Berzal

2. Aprovechamiento de los recursos del sistema


Cualquier operacin que pueda bloquear nuestra aplicacin
durante un perodo de tiempo apreciable es recomendable que se
realice de forma independiente.
La CPU es el dispositivo ms rpido del ordenador: Desde
su punto de vista, todos los dems dispositivos del
ordenador son lentos, desde una impresora hasta un disco
duro con Ultra-DMA.
En un entorno distribuido, las operaciones de E/S son an
ms lentas, ya que el tiempo necesario para acceder a un
recurso disponible en otra mquina a travs de una red
depende, entre otros factores, de la carga de la mquina a la
que accedemos y del ancho de banda del que dispongamos.

Paralelismo real
Su aprovechamiento requiere el uso de hebras y procesos
Un sistema multiprocesador dispone de varias CPUs.
Un cluster de ordenadores est compuesto por un conjunto
de ordenadores conectados entre s, a los que se accede
como si se tratase de un nico ordenador.
Algunas versiones del Pentium 4 de Intel incorporan
Simultaneous MultiThreading (SMT), que Intel denomina
comercialmente Hyper-Threading, con lo que un nico
microprocesador puede funcionar como si tuvisemos un
multiprocesador.

Concurrencia

-5-

Fernando Berzal

3. Modularizacin: Paralelismo implcito


A veces, los motivos que nos llevan a utilizar hebras o procesos
no tienen una justificacin fsica, sino que un programa puede
disearse con ms comodidad si lo descomponemos en un
conjunto de tareas independientes.
Un ejemplo mundano
El problema de perder peso puede verse como una
combinacin de dos actividades: hacer ejercicio y mantener
una dieta equilibrada. Ambas deben realizarse durante el
mismo perodo de tiempo, aunque no necesariamente a la vez.
En situaciones de este tipo, la concurrencia de varias actividades
es la solucin adecuada para un problema: la solucin natural al
problema implica concurrencia, mientras que una solucin
secuencial sera extremadamente difcil.
Ejemplos: Simulaciones, videojuegos

IMPORTANTE
El objetivo principal del uso de paralelismo es
mejorar el rendimiento del sistema.
El uso de paralelismo (hebras o procesos) permite mejorar el
tiempo de respuesta de una aplicacin
o la carga de trabajo que puede soportar el sistema.
No obstante, un nmero excesivo de hebras o procesos puede
llegar a degradar el rendimiento del sistema (debido al tiempo de
CPU requerido por los cambios de contexto): hay que analizar
hasta qu punto compensa utilizar hebras y procesos.

Concurrencia

-6-

Fernando Berzal

Ejecucin de procesos
La mquina virtual Java nos asla de los detalles particulares de la
mquina en la que se ejecutan nuestras aplicaciones. No obstante,
La clase System nos permite acceder a recursos del sistema
de forma portable (aunque de una forma muy rudimentaria):
o Usar los dispositivos de E/S estndar
System.in & System.out
o Acceder a algunas variables de entorno
System.getProperties()

La clase Runtime nos permite ejecutar comandos del


sistema operativo y controlar la mquina virtual Java
(ver cunta memoria queda libre o forzar la ejecucin del
recolector de basura, por ejemplo).

OJO! Para mantener la portabilidad de nuestras aplicaciones,


es aconsejable evitar, en la medida que sea posible, el uso de
caractersticas especficas de un sistema operativo concreto.
Concurrencia

-7-

Fernando Berzal

La ejecucin de procesos es responsabilidad del sistema


operativo, del cual nos asla la mquina virtual Java, si bien
podemos usar la clase Runtime:
1. Slo existe una instancia de la clase Runtime, que se obtiene con:
Runtime rt = Runtime.getRuntime();

2. El objeto obtenido con la llamada a Runtime.getRuntime()


nos permite ejecutar procesos con
rt.exec(miprograma);

Ejemplo (NO PORTABLE)


public class Procesos
{
public static void main(String[] args)
throws java.io.IOException
{
Runtime rt = Runtime.getRuntime();
rt.exec("cmd /c start iexplore http://elvex.ugr.es/");
}
}

Podemos evitar el uso del shell (cmd.exe) si especificamos la ruta


completa del programa que deseamos ejecutar, p.ej.
c:/Archivos de Programa/Internet Explorer/iexplore.exe

Si estuvisemos usando UNIX, deberamos haber escrito algo como:


rt.exec("/usr/mozilla/mozilla-bin http://elvex.ugr.es/");

En Windows, tambin podemos omitir el nombre del programa y


poner directamente la ruta del recurso al que queremos acceder
(el shell del S.O. se encarga de buscar cul es el programa adecuado):
rt.exec("cmd /c start http://elvex.ugr.es/");
rt.exec("cmd /c start mailto:fberzal@decsai.ugr.es");
rt.exec("cmd /c apuntes.doc");
Concurrencia

-8-

Fernando Berzal

Ejecucin de hebras
En realidad, todas las aplicaciones escritas en Java son
aplicaciones multihebra (recuerde el recolector de basura).

Hebras vs. Procesos


Los cambios de contexto son ms costosos en el caso de los
procesos al tener que cambiar el espacio de direcciones en el
que se trabaja.
La comunicacin entre procesos que se ejecutan en distintos
espacios de memoria es ms costosa que cuando se realiza a
travs de la memoria que comparten las distintas hebras de
un proceso.
Sin embargo, un fallo en una hebra puede ocasionar la cada
completa de la aplicacin mientras que, si se crean procesos
independientes, los fallos se pueden contener en el interior
de un proceso, con lo que la tolerancia a fallos de la
aplicacin ser mayor.

Creacin y ejecucin de hebras en Java


La forma ms sencilla de crear una hebra en Java es disear una
subclase de java.lang.Thread.
En la subclase redefiniremos el mtodo run(), que viene a ser
algo as como el main() de una hebra.
Para comenzar la ejecucin paralela de la nueva hebra, usaremos
su mtodo start().

Concurrencia

-9-

Fernando Berzal

public class HebraContador extends Thread


{
private int contador = 10;
private static int hebras = 0;
// Constructor
public HebraContador()
{
super("Hebra " + ++hebras);
}
// Salida estndar
public String toString()
{
return getName() + ": " + contador;
}
// Ejecucin de la hebra
public void run()
{
while (contador>0) {
System.out.println(this);
contador--;
}
}
// Programa principal
public static void main(String[] args)
{
int
i;
Thread hebra;
for (i = 0; i < 5; i++)
hebra = new HebraContador();
hebra.start();
}
}
}
Concurrencia

- 10 -

Fernando Berzal

El orden en que se realizan las operaciones de las distintas


hebras puede cambiar de una ejecucin a otra
(en funcin de cmo se asigne la CPU
a la distintas hebras de nuestro programa).
NOTA:

En el ejemplo anterior, lo ms probable es que


las cinco hebras se ejecuten secuencialmente
salvo que incrementemos el valor inicial del contador.

Si queremos ceder explcitamente la CPU para que se le asigne a


otra hebra distinta a la actual, podemos utilizar yield():
public void run()
{
while (contador>0) {
System.out.println(this);
contador--;
yield();
}
}

El mtodo yield() no se suele utilizar en la prctica, aunque s


suele ser til detener la ejecucin de una hebra durante un perodo
de tiempo determinado (expresado en milisegundos) con una
llamada al mtodo sleep():
public void run()
{
while (contador>0) {
System.out.println(this);
contador--;
try {
sleep(1000);
} catch (InterruptedException e) {
}
}
}
Concurrencia

- 11 -

Fernando Berzal

Como Java slo soporta herencia simple y puede que el objeto


que representa nuestra hebra sea mejor implementarlo como
subclase de otra clase de nuestro sistema, Java nos permite crear
una hebra a partir de cualquier objeto que implemente la interfaz
Runnable, que define nicamente un mtodo run():

public class Contador implements Runnable


{
private String id;
private int
contador = 10;
private static int hebras = 0;
public Contador()
{
hebras++;
id = "Hebra " + hebras;
}
public void run()
{
while (contador>0) {
System.out.println(this);
contador--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
public static void main(String[] args)
{
int
i;
Thread hebra;
for (i = 0; i < 5; i++) {
hebra = new Thread ( new Contador() );
hebra.start();
}
}
}
Concurrencia

- 12 -

Fernando Berzal

La prioridad de las hebras


La prioridad de una hebra le indica al planificador de CPU la
importancia de una hebra, de tal modo que le asignar ms tiempo
de CPU a las hebras de mayor prioridad.
La prioridad de una hebra se cambia con una llamada al mtodo
setPriority(), usualmente en el constructor de la hebra:
public class HebraContador extends Thread

public HebraContador (int prioridad)


{
super("Hebra " + ++hebras);
setPriority (prioridad);
}

Por defecto, la prioridad de las hebras es


Thread.NORM_PRIORITY

En el siguiente fragmento de cdigo, la ltima hebra que


lanzamos se ejecutar antes que las dems:
int
i;
Thread hebra;
for (i = 0; i < 5; i++) {
hebra = new HebraContador (Thread.MIN_PRIORITY);
hebra.start();
}
hebra = new HebraContador (Thread.MAX_PRIORITY);
hebra.start();

Cuando en nuestra aplicacin tenemos varias hebras ejecutndose,


les daremos mayor prioridad aquellas hebras cuyo tiempo de
respuesta deba ser menor.

Concurrencia

- 13 -

Fernando Berzal

Finalizacin de la ejecucin de una hebra


Se puede utilizar el mtodo join() de la clase Thread para
esperar la finalizacin de la ejecucin de una hebra:

private static final int N = 5;


public static void main(String[] args)
{
int
i;
Thread hebra[] = new Thread[N];
for (i=0; i<N; i++) {
hebra[i] = new HebraContador(Thread.NORM_PRIORITY);
hebra[i].start();
}
for (i=0; i<5; i++) {
try {
hebra[i].join();
} catch (InterruptedException e) {
}
System.out.println (hebra[i]+" ha terminado");
}
System.out.println
(El programa principal ha terminado");
}

Concurrencia

- 14 -

Fernando Berzal

Uso de recursos compartidos


Cada proceso o hebra se ejecuta de forma independiente. Sin
embargo, cuando varias hebras (o procesos) han de acceder a un
mismo recurso, se ha de coordinar el acceso a ese recurso.
Ejemplos
Una impresora compartida en red debe imprimir los documentos
enviados por distintos usuarios uno detrs de otro, sin mezclar
partes de uno con partes de otro.
Cuando varias hebras (o procesos) acceden a los mismos datos
(ya sea en memoria o en un fichero), hemos de tener mucho
cuidado a la hora de actualizarlos.

Proceso 1
Ingreso en una cuenta
P1.A Obtener saldo actual

Proceso 2
Transferencia a otra cuenta
P2.A Obtener saldo actual

++
-P1.B Guardar saldo modificado P2.B Guardar saldo modificado


 


Si el saldo
inicial
 de
 lacuenta
!
"es#$de
%1000
& ' ( "

de 500
*)
de la cuenta sea de 750
Ahora bien, en funcin de cmo se ordenen las operaciones de las
dos tareas independientes (el ingreso y la transferencia), el
resultado final puede ser muy distinto:

+

+

+

+

P1.A+(lee
, 1000
-/.) P2.A (lee
+ 1000 P1.B (escribe
B (escribe 250 , por lo que nos quedan 250 .
1500
P2.A
P1.A (lee +
1000 P2.B (almacena
+(lee
, -11000
0)
250
B (almacena 1500 , por lo que tenemos 1500
al final ;-)
Concurrencia

- 15 -

Fernando Berzal

El problema proviene de que no sabemos en qu momento se le


asignar la CPU a cada hebra/proceso.
Si lo nico que nos interesa es leer datos desde distintas tareas
independientes, podemos hacerlo en paralelo sin problemas.
Sin embargo, en el momento en el que queramos realizar alguna
modificacin, hemos de evitar que otras tareas accedan al recurso
compartido mientras nosotros estamos usndolo (para que no lean
valores incorrectos ni interfieran con lo que estemos haciendo).

Mecanismos de exclusin mutua


Una solucin para este problema consiste en que, para acceder a
un recurso compartido, haya antes que adquirirlo.
La hebra que adquiere el recurso bloquea el acceso a l.
Las dems hebras, para acceder al recurso, intentarn adquirirlo y
se quedarn bloqueadas hasta que lo libere la hebra que lo posee.
De esta forma, el acceso al recurso compartido se realiza
secuencialmente (por lo que deberemos tener cuidado para no
eliminar completamente el paralelismo de nuestra aplicacin).
IMPORTANTE
Un programa debe avanzar hasta proporcionar una respuesta.
En el caso de los programas secuenciales, la existencia de un
bucle infinito es la nica causa posible de que el programa no
proporcione respuesta alguna.
Cuando trabajamos con aplicaciones multihebra, pueden aparecer
bloqueos [deadlocks] que se ocasionan cuando cada hebra se
queda esperando a que otra de las hebras bloqueadas libere un
recurso compartido al que quiere acceder.
Concurrencia

- 16 -

Fernando Berzal

synchronized
Java permite definir secciones crticas (fragmentos de cdigo que
slo puede estar ejecutando una hebra) mediante la palabra
reservada synchronized:

synchronized (objeto) {
// A este bloque de cdigo
// slo puede acceder una hebra
// en cada momento
}

Si tenemos un objeto cuyo estado queremos actualizar desde


distintas hebras de forma coordinada, podemos etiquetar con
synchronized todos aquellos mtodos cuya ejecucin
concurrente podra causar algn tipo de error:
public class Cuenta
{
private int saldo;
public synchronized void ingreso (int cantidad)
{
saldo += cantidad;
}
public synchronized void retirada (int cantidad)
{
saldo -= cantidad;
}
}

Cuando se est ejecutando un mtodo synchronized asociado a


un objeto, el objeto se bloquea y no se puede ejecutar ningn otro
mtodo synchronized del objeto hasta que termine la ejecucin
del mtodo que bloque el acceso al objeto.
Concurrencia

- 17 -

Fernando Berzal

Ejemplo: Realizacin de reservas


if (asiento.disponible())
asiento.reservar();

Si justo despus de comprobar que el asiento est disponible y


antes de hacer la reserva, se asigna la CPU a otra hebra, sta
podra comprobar que el asiento est libre y reservarlo.
Cuando el control de la CPU vuelva a la primera hebra (que ya
haba comprobado la disponibilidad de asientos), sta tambin
har tambin la reserva (con lo que tendremos overbooking).

Para eliminar el problema, podemos:


1. Incluir el bloque de cdigo en una seccin crtica:
synchronized (asiento) {
if (asiento.disponible())
asiento.reservar();
}

2. Marcar con synchronized los mtodos disponible() y


reservar() de la clase Asiento, adems de cualquier otro mtodo
que pueda modificar el estado del asiento y de asegurarnos de que las
operaciones se completan correctamente:
public class Asiento
{

public synchronized boolean disponible ()


{}
public synchronized void reservar ()
throws AsientoYaReservadoException
{}
}
Concurrencia

- 18 -

Fernando Berzal

Sobre el uso de mecanismos de exclusin mutua


No hay que abusar del uso de mecanismos secciones crticas. Cada cerrojo que se usa
impide potencialmente el progreso de la ejecucin de otras hebras de la aplicacin. Las
secciones crticas eliminan el paralelismo y, con l, muchas de las ventajas que nos
llevaron a utilizar hebras en primer lugar. En un caso extremo, la aplicacin puede
carecer por completo de paralelismo y convertirse en una aplicacin secuencial pese a
que utilicemos hebras en nuestra implementacin.
La ausencia de paralelismo no es, ni mucho menos, el peor problema que se nos puede
presentar durante el desarrollo de una aplicacin multihebra. El uso de mecanismos de
sincronizacin como cerrojos o monitores puede conducir a otras situaciones poco
deseables que tambin hemos de tener en cuenta:
Interbloqueos [deadlocks]: Una hebra se bloquea cuando intenta bloquear el
acceso a un objeto que ya est bloqueado. Si dicho objeto est bloqueado por una
hebra que, a su vez, est bloqueada esperando que se libere un objeto bloqueado por
la primera hebra, ninguna de las dos hebras avanzar. Ambas se quedarn esperando
indefinidamente. El interbloqueo es consecuencia de que el orden de adquisicin de
los cerrojos no sea siempre el mismo y la forma ms evidente de evitarlo es asegurar
que los cerrojos se adquieran siempre en el mismo orden.
Inanicin [starvation], cuando una hebra nunca avanza porque siempre hay otras a
las que se les da preferencia. Por ejemplo, si le damos siempre prioridad a un
lector frente a un escritor, el escritor nunca obtendr el cerrojo para modificar el
recurso compartido mientras haya lectores. Los escritores "se morirn de inanicin".
Inversin de prioridad: El planificador de CPU decide en cada momento qu
hebra, de entre todas las no bloqueadas, ha de disponer de tiempo de CPU.
Usualmente, esta decisin viene influida por la prioridad de las hebras. Sin embargo,
al usar cerrojos se puede dar el caso de que una hebra de prioridad alta no avance
nunca, justo lo contrario de lo que su prioridad nos podra hacer pensar. Imaginemos
que tenemos tres hebras H1, H2 y H3, de mayor a menor prioridad. H3 est
ejecutndose y bloquea el acceso al objeto O. H2 adquiere la CPU al tener ms
prioridad que H3 y comienza un clculo muy largo. Ahora, H1 le quita la CPU a H2
y, al intentar adquirir el cerrojo de O, queda bloqueada. Entonces, H2 pasa a
disponer de la CPU para proseguir su largo cmputo. Mientras, H1 queda bloqueada
porque H3 no llega a liberar el cerrojo de O. Mientras que H3 no disponga de algo
de tiempo de CPU, H1 no avanzar y H2, pese a tener menor prioridad que H1, s
que lo har. El planificador de CPU puede solucionar el problema si todas las hebras
disponibles avanzan en su ejecucin, aunque sea ms lentamente cuando tienen
menor prioridad. De ah la importancia de darle una prioridad alta a las hebras cuyo
tiempo de respuesta haya de ser bajo, y una prioridad baja a las hebras que realicen
tareas muy largas.
Todos estos problemas ponen de manifiesto la dificultad que supone trabajar con
aplicaciones multihebra. Hay que asegurarse de asignar los recursos cuidadosamente
para minimizar las restricciones de acceso en exclusiva a recursos compartidos. En
muchas ocasiones, por ejemplo, se puede simplificar notablemente la implementacin
de las aplicaciones multihebra si hacemos que cada una de las hebras trabaje de forma
independiente, incluso con copias distintas de los mismos datos si hace falta. Sin datos
comunes, los mecanismos de sincronizacin se hacen innecesarios.
Concurrencia

- 19 -

Fernando Berzal

Hebras e interfaces de usuario


Cuando ejecutamos una aplicacin con una interfaz grfica de
usuario, automticamente se crea una hebra que se encarga de
procesar todos los eventos asociados a la interfaz de usuario.
Cuando nuestra aplicacin ha de realizar alguna operacin costosa
en tiempo de ejecucin, esta operacin hemos de realizarla en una
hebra aparte. Si no lo hacemos as, podemos encontrarnos con
algo como lo siguiente:

Si mantenemos ocupada la hebra que se encarga de gestionar los


eventos de la interfaz de usuario, sta dejar de responder al
usuario (la ventana deja de refrescarse y no podemos controlar la
ejecucin de la aplicacin).
Por tanto, crearemos una hebra independiente cada vez que
necesitemos realizar tareas largas (de ms de un par de segundos):

Al usar una hebra auxiliar [worker thread], nuestra aplicacin se


comportar como cabra esperar
Concurrencia

- 20 -

Fernando Berzal

siempre que tengamos cuidado a la hora de utilizar recursos


compartidos entre las distintas hebras.

Por ejemplo, si nuestras hebras auxiliares tambin acceden a los


componentes Swing, estamos usando un recurso compartido:

Cuando esto sucede, pueden darse situaciones desagradables si no


controlamos el acceso a los recursos compartidos.
La solucin ms sencilla consiste en eliminar el recurso
compartido, de tal forma que slo una de las hebras pueda acceder
a lo que antes era un recurso compartido: se elimina el acceso
concurrente a un recurso desde distintas hebras.
Por convencin, la hebra responsable de gestionar los eventos de
la interfaz de usuario ser siempre responsable de manipular
todos los componentes y controles de nuestra interfaz.

Concurrencia

- 21 -

Fernando Berzal

SwingUtilities.invokeLater()

SWING

== EnventQueue.invokeLater()

AWT

Para hacer que la hebra encargada de los eventos se encargue


tambin de ejecutar un fragmento de cdigo, se utiliza el mtodo
SwingUtilities.invokeLater().
El mtodo invokeLater() recibe como parmetro un objeto que
implemente la interfaz Runnable.
Por tanto, deberemos encapsular en el mtodo run() de un objeto
Runnable lo que queramos hacer sobre los componentes de la
interfaz desde una hebra independiente.

Una variante de invokeLater() es el mtodo


SwingUtilities.invokeAndWait(), que detiene la
ejecucin de la hebra auxiliar hasta que la hebra
principal de la interfaz haya ejecutado el cdigo
correspondiente al objeto Runnable que se le pasa
como parmetro a invokeAndWait().
Concurrencia

- 22 -

Fernando Berzal

javax.swing.Timer
Cuando lo que queremos es realizar una operacin de forma
peridica, no es necesario que creemos explcitamente una hebra.
Podemos utilizar la clase javax.swing.Timer, que asociaremos
a un ActionListener encargado de realizar la operacin:

// Animacin a X fps (frames por segundo)


public class Animator
extends JFrame
implements ActionListener
{

Timer timer;
public Animator (int fps)
{
timer = new Timer(1000/fps, this);

}
public void startAnimation()
{
timer.start();
}
public void stopAnimation()
{
timer.stop();
}
public void actionPerformed (ActionEvent e)
{
// Mostrar el siguiente frame

repaint();
}

}
Concurrencia

- 23 -

Fernando Berzal

Ms informacin
The JavaTM Tutorial
Threads: Doing Two or More Tasks At Once
http://java.sun.com/docs/books/tutorial/essential/threads/

Bruce Eckel:
Thinking in Java [3rd edition]. Chapter 13: Concurrency
http://www.mindview.net/Books/TIJ/

Concurrent Programming Using Java


http://elvis.rowan.edu/~hartley/ConcProgJava/index.html

Threads and Swing


http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html

Using a worker thread


http://java.sun.com/products/jfc/tsc/articles/threads/threads2.html

Concurrencia

- 24 -

Fernando Berzal

Distribucin
Mecanismos de comunicacin entre procesos
Redes de ordenadores: Internet
Sockets
Sockets TCP
Creacin de un cliente TCP
Creacin de un servidor TCP
Sockets UDP
La clase URL
RMI (Remote Method Invocation)
Extensiones: Jini
Alternativas: CORBA y .NET Remoting

the network is the computer


Lema de Sun Microsystems

Comunicaci
omunicacin
n entre procesos
El desarrollo de aplicaciones concurrentes involucra el uso de
mecanismos de comunicacin. Estos mecanismos, conocidos
genricamente como mecanismos de comunicacin entre
procesos (IPC) permiten que los distintos procesos que
conforman una aplicacin "hablen entre s".
Los procesos en los que se descompone una aplicacin pueden
ejecutarse en un mismo ordenador (siempre que tengamos un
sistema operativo multitarea) o en mquinas diferentes. En este
ltimo caso, la comunicacin entre procesos involucra el uso de
redes de ordenadores.

Mecanismos de comunicacin entre procesos


[IPC: InterProcess Communication]
Cuando en un sistema tenemos distintos procesos, necesitamos
disponer de mecanismos que hagan posible la comunicacin entre
ellos. Se pueden utilizar distintos mecanismos de comunicacin
entre procesos:
Pipes annimos [Anonymous pipes]: Permiten redireccionar la
entrada o salida estndar de un proceso (utilizando | en la lnea
de comandos, por ejemplo).
Sockets: Usan la familia de protocolos TCP/IP (la que se utiliza
en Internet). Su diseo original proviene del BSD UNIX
[Berkeley Software Distribution].
Estndares de paso de mensajes como MPI (Message Passing
Interface, muy utilizado en clusters y supercomputadores) o
PVM (Parallel Virtual Machina, otro estndar utilizado en
multiprocesadores y multicomputadores).
Distribucin

-1-

Fernando Berzal

Llamadas a procedimientos remotos (RPC: Remote Procedure


Call): Permiten realizar la comunicacin entre procesos como
si se tratase de simples llamadas a funciones.
o En Java, se utiliza un mecanismo conocido como RMI
[Remote Method Invocation].
o En la plataforma .NET, se utiliza .NET Remoting (un
mecanismo similar a RMI)
o El RPC de Windows cumple con el estndar OSF DCE
[Open Software Foundation Distributed Computing
Environment], lo que permite la comunicacin entre
procesos que se ejecuten en sistemas operativos
diferentes a Windows.
Middleware: Software que se utiliza para conectar los
componentes de un sistema distribuido.
o CORBA [Common Object Request Broker Architecture],
estndar del OMG [Object Management Group].
o Servicios web [Web services], promovidos por el W3C
(el consorcio que propone los estndares usados en la web).
o J2EE [Java 2 Enterprise Edition] estandariza los servicios
que ha de ofrecer un servidor de aplicaciones Java.
Sun Microsystems
o COM / DCOM [Component Object Model / Distributed
COM] establece un estndar binario mediante el cual se
puede acceder a los servicios ofrecidos por un
componente. Microsoft Corporation
Como se puede ver, disponemos de una amplia variedad de
mecanismos de comunicacin entre procesos (y eso sin contar los
mltiples mecanismos especficos que ofrece cada sistema
operativo).
En el caso particular de Windows: el portapapeles, DDE [Dynamic
Data Exchange], OLE [Object Linking and Embedding], ActiveX,
Mailslots (en Win32 y OS/2), el mensaje WM_COPYDATA, ficheros
mapeados en memoria, pipes con nombre [Named pipes], semforos,
eventos, mutex y otras primitivas de sincronizacin
Distribucin

-2-

Fernando Berzal

Independientemente del mecanismo de comunicacin entre


procesos que decidamos emplear, nuestra aplicacin debera
acceder a los recursos externos de la misma forma que accede a
recursos locales.
Para encapsular el acceso a recursos externos se suelen emplear
proxies o gateways (para que en nuestra aplicacin se pueda
cambiar el mecanismo de comunicacin entre procesos con el
menor esfuerzo posible):

Siempre debemos tener en cuenta que


Los mecanismos de comunicacin no siempre son fiables
(algunos paquetes se pierden)
La comunicacin entre procesos consume tiempo
(la latencia no es cero)
La capacidad del canal de comunicacin no es infinita
(el ancho de banda es un recurso muy valioso)
Las comunicaciones no siempre se realizan a travs de medios
seguros.
TERMINOLOGA: Los procesos de una aplicacin distribuida
suelen clasificarse como clientes o servidores, si bien pueden
desempear ambos roles en distintos momentos. El cliente es el
que solicita algn servicio proporcionado por otro proceso. El
servidor es el que atiende las peticiones de los clientes.
Distribucin

-3-

Fernando Berzal

Redes de ordenadores: Internet


TERMINOLOGA
Red de ordenadores
Conjunto de sistemas autnomos interconectados.
Protocolo
Conjunto de reglas para que emisor y receptor
interpreten de forma adecuada los datos que se transmiten.

Origen de Internet
Proyecto del US Defense Advanced Research Project Agency
(DARPA) para el desarrollo de su red ARPANET.

Objetivo
Tolerancia a errores en los elementos de la subred.

Diseo original de ARPANET

Distribucin

-4-

Fernando Berzal

Evolucin de ARPANET

(a)
(b)
(c)
(d)
(e)

Diciembre 1969
Julio 1970
Marzo 1971
Abril 1972
Septiembre 1972

Arquitectura actual de Internet

Distribucin

-5-

Fernando Berzal

La familia de protocolos TCP/IP

El protocolo IP [Internet Protocol] se utiliza para transmitir


paquetes (fragmentos de datos) de un ordenador a otro en Internet.
Para saber a dnde van dirigidos los datos, a cada ordenador se le
asigna una direccin IP:

Los protocolos TCP y UDP permiten la existencia de varias


conexiones con una misma direccin IP (multiplexacin de
conexiones). Adems de la direccin IP, cuando queremos
conectarnos con una aplicacin hemos de especificar un nmero
de puerto TCP o UDP.
Distribucin

-6-

Fernando Berzal

El protocolo TCP [Transmission Control Protocol] proporciona


un conjunto de primitivas de servicio (operaciones bsicas) con
las que se pueden construir aplicaciones que requieran servicios
orientados a conexin (aqullas en las que primero se establece
una conexin y luego se transmiten los datos).
TCP tambin se encarga de reordenar los datos si stos se reciben
desordenados y de pedir automticamente que se retransmitan los
datos si se produce un error en la transmisin.
Las distintas aplicaciones que se usan en Internet se suelen
construir sobre TCP y suelen estar asignadas a puertos estndar:
Puerto
21
23
25
79
80
110
119

Protocolo
FTP
Telnet
SMTP
Finger
HTTP
POP3
NNTP

Uso
Transferencia de ficheros
Acceso remoto
Envo de correo electrnico
Informacin acerca de usuarios
World Wide Web
Lectura de correo electrnico
Grupos de noticias USENET

El protocolo UDP [User Datagram Protocol] proporciona


servicios no orientados a conexin, no garantiza la entrega de los
paquetes, ni su llegada en orden, ni la no existencia de duplicados.
UDP se utiliza en algunas aplicaciones,
como SNMP [Simple Network Management Protocol]
o RTP [Real-time Transport Protocol]

ACLARACIN:
El telfono proporciona un servicio orientado a conexin,
mientras que el correo ofrece servicios no orientados a conexin.
Distribucin

-7-

Fernando Berzal

El servicio de nombres DNS [Domain Name Service] es una


aplicacin que se utiliza en Internet para convertir un nombre
(ms fcil de recordar) en una direccin IP.
En Internet,
los nombres se agrupan en dominios de forma jerrquica:

Para identificar un recurso concreto en Internet, hay que


especificar la direccin IP en la que se encuentra el recurso, el
protocolo que se utiliza para acceder a l y el puerto a travs del
cul se establece la conexin. Toda esta informacin se recoge en
una URL [Uniform Resource Locator]:

Distribucin

-8-

Fernando Berzal

Sockets
La biblioteca estndar de clases de Java nos proporciona todo lo
que necesitamos para utilizar sockets en nuestras aplicaciones en
el paquete java.net, por lo que tendremos que aadir la
siguiente lnea al comienzo de nuestros ficheros de cdigo:
import java.net.*;

Los sockets son un mecanismo de comunicacin entre procesos


que se utiliza en Internet.
Un socket (literalmente, enchufe) es un extremo de una
comunicacin en Internet, por lo que se identifica con una
direccin IP (un nmero entero de 32 bits) y un puerto (un
nmero entero de 16 bits).
NOTA: Java encapsula el concepto de direccin
IP con la clase java.net.InetAddress

Existen dos tipos de sockets, en funcin de si queremos utilizar


TCP (orientado a conexin) o UDP (no orientado a conexin)
Socket y ServerSocket se utilizan para establecer

conexiones y enviar datos utilizando el protocolo TCP.


DatagramSocket se utiliza para transmitir datos usando UDP.

Distribucin

-9-

Fernando Berzal

Sockets TCP
Las clases Socket y ServerSocket permiten utiliza el
protocolo TCP en Java:
Un Socket se utiliza para transmitir y recibir datos.
Un ServerSocket nunca se utiliza para transmitir datos. Su
nico cometido es, en el servidor, esperar a que un cliente
quiera establecer una conexin con el servidor.

Funcionamiento
El cliente crea un Socket para solicitar una conexin con el
servidor al que desea conectarse.

Cuando el ServerSocket recibe la solicitud, crea un Socket en


un puerto que no se est usando y la conexin entre cliente y
servidor queda establecida.

Entonces, el SocketServer vuelve a quedarse escuchando para


recibir nuevas peticiones de clientes.

Distribucin

- 10 -

Fernando Berzal

Transmisin de datos
Cuando la conexin queda establecida, los dos sockets conectados
pueden comunicarse entre s mediante operaciones de lectura y
escritura idnticas a las cualquier otro stream en Java (read y
write).
La entrada y la salida de un socket se representan en Java mediante
las clases InputStream y OutputStream, respectivamente (las
mismas que se utilizan para trabajar con ficheros).

Creacin de un cliente TCP: Conexin a un servidor web


Un caso particular de socket TCP es el socket que se utiliza para
conectarse a un servidor web. Los servidores web suelen escuchar
peticiones en el puerto 80 TCP y emplean el protocolo HTTP.

Tras establecer la conexin TCP con el servidor web, se realiza


una peticin HTTP como la siguiente:
GET ejemplo.html

Si el fichero ejemplo.html existe, el servidor nos lo devuelve:


<HTML>
<HEAD>
<TITLE>Pgina web de ejemplo</TITLE>
</HEAD>
<BODY>

</BODY>
</HTML>
Distribucin

- 11 -

Fernando Berzal

El siguiente fragmento de cdigo muestra cmo nos podemos


conectar a un servidor web para obtener un fichero de forma
remota (/ en este caso, la pgina principal del servidor web):

Socket
PrintWriter
InputStreamReader
BufferedReader
String

socket;
out;
reader;
in;
line;

// Conexin TCP
try {
socket = new Socket("elvex.ugr.es", 80);
} catch (UnknownHostException e) {
System.err.println("Host desconocido";
}
// Streams de E/S
out = new PrintWriter(socket.getOutputStream());
reader = new InputStreamReader(socket.getInputStream());
in = new BufferedReader(reader);
// Solicitud HTTP
out.println("GET /");
out.println("");
out.flush();
// Respuesta HTTP
line = in.readLine();
while (line!=null) {
System.out.println(line);
line = in.readLine();
}
// Cierre de la conexin
out.close();
in.close();
socket.close();
Distribucin

- 12 -

Fernando Berzal

Creacin de un servidor TCP: Servido de eco


import java.net.*;
import java.io.*;
class EchoServer
{
public static void main( String args[] )
throws IOException
{
ServerSocket
serverSocket;
Socket
clientSocket;
BufferedReader in;
PrintWriter
out;
String
mensaje;
Bolean
terminar = false;
serverSocket = new ServerSocket(4444);
while (!terminar) {
clientSocket = serverSocket.accept();
out = new PrintWriter(
clientSocket.getOutputStream());
in = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
mensaje = in.readLine();
out.println(mensaje);
out.flush();
terminar = mensaje.equals("FIN");
in.close();
out.close();
clientSocket.close();
}
serverSocket.close();
}
}
Distribucin

- 13 -

Fernando Berzal

El servidor anterior se instala en el puerto 4444 TCP y se queda


esperando peticiones en la llamada al mtodo accept().
Cuando se acepta la peticin, a travs del InputStream asociado
al socket se lee una lnea de texto enviada por el cliente.
Esa misma lnea de texto se le enva al cliente a travs del
OutputStream asociado al socket.
Despus, se cierra la conexin con el cliente y el servidor se vuelve
a quedar esperando la llegada de nuevas solicitudes de eco.
El servidor seguir ejecutndose hasta que reciba una peticin de
un cliente que solicite el eco de FIN.
Si queremos probar el servidor, podemos usar la utilidad telnet
para conectarnos al puerto 4444 de la mquina local con:
telnet localhost 4444

Cualquier cliente Java puede acceder a nuestro servidor de eco


utilizando el siguiente fragmento de cdigo:
BufferedReader in;
PrintWriter
out;
Socket socket = new Socket("localhost",4444);
out = new PrintWriter(socket.getOutputStream());
in

= new BufferedReader(
new InputStreamReader(
socket.getInputStream()));

out.println(args[0]);
out.flush();
String eco = in.readLine();
System.out.println(eco);
in.close();
out.close();
socket.close();

Distribucin

- 14 -

Fernando Berzal

Creacin de un servidor TCP: Servidor de hora


Wed May 18 18:18:18 CEST 2005
import java.net.*;
import java.io.*;
class DateServer
{
public static void main( String args[] )
throws IOException {
ServerSocket serverSocket;
Socket
clientSocket;
PrintWriter out;
serverSocket = new ServerSocket(666);
try {
while (true) {

// OJO!

clientSocket = serverSocket.accept();
out = new PrintWriter
(clientSocket.getOutputStream());
out.println(new java.util.Date());
out.flush();
out.close();
clientSocket.close();
}
} catch (IOException error) {
serverSocket.close();
}
}
}

NOTA: El servidor es lo suficientemente simple como para atender


todas las peticiones secuencialmente. Si el procesamiento de cada
solicitud proveniente de un cliente fuese ms costoso, deberamos
utilizar hebras para atender en paralelo a distintos clientes (y
usaramos protocolos algo ms complejos para hacer algo ms til).
Distribucin

- 15 -

Fernando Berzal

IMPORTANTE
Los servidores, usualmente, han de atender mltiples peticiones
provenientes de distintos clientes, por lo que siempre debemos
implementarlos como aplicaciones multihebra.

El pseudocdigo de cualquier servidor es siempre similar a:


while (!fin) {
// 1. Aceptar una solicitud

// 2. Crear una hebra independiente


//
para procesar la solicitud

Sockets UDP
El tipo ms sencillo de sockets, puesto que no es necesario
establecer ninguna conexin para enviar y recibir datos.
En Java, un objeto de tipo DatagramSocket representa un socket
UDP y puede enviar o recibir datos directamente de otro socket UDP.
Los datos se envan y reciben en paquetes autocontenidos
denominados datagramas (igual que el correo convencional).
Los datagramas se representan en Java mediante la clase
DatagramPacket, que consiste simplemente en un array de bytes
dirigido a una direccin IP y a un puerto UDP concretos.
La clase MulticastSocket se puede emplear para enviar un
mismo datagrama a muchos destinatarios simultneamente.
Ejemplos disponibles en:
http://java.sun.com/docs/books/tutorial/networking/datagrams/
Distribucin

- 16 -

Fernando Berzal

La clase URL
Cuando alguien accede a un servidor web, generalmente lo hace
para obtener un documento, para lo que usa una URL (que en java
se representa mediante la clase java.net.URL).
El siguiente fragmento de cdigo muestra cmo podemos crear
una URL y acceder a un recurso en Internet a partir de la URL:
URL url = new URL("http://elvex.ugr.es/");
// Datos de la URL
System.out.println("Protocolo = " + url.getProtocol());
System.out.println("Host = " + url.getHost());
System.out.println("Fichero = " + url.getFile());
System.out.println("Puerto = " + url.getPort());
// Acceso al contenido asociado a la URL
InputStreamReader reader = new InputStreamReader(
url.openStream());
BufferedReader in = new BufferedReader(reader);
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();

De esta forma no tenemos que conocer los detalles del protocolo


HTTP que utilizan los servidores web (ni la direccin IP del
servidor, ya que la clase URL se encarga de traducir el nombre del
host a una direccin IP usando el servicio DNS).
NOTA:
Con URL.openConnection() podemos establecer una conexin
TCP a travs de la cual tambin se pueden transmitir datos.
Distribucin

- 17 -

Fernando Berzal

RMI
[Remote Method Invocation]
Cuando utilizamos sockets, hemos de preocuparnos de cmo se
transmiten fsicamente los datos entre los extremos de una
conexin (a nivel de bytes, ya que usamos los streams estndar)
RMI permite olvidarnos de los detalles de la transmisin de datos
y centrarnos en el diseo de la lgica de nuestra aplicacin,
puesto que nos permite acceder a un objeto remoto como si de un
objeto local se tratase.
Internamente, RMI utiliza serializacin de objetos para
encargarse de la transmisin de datos a travs de la red (de
cara al programador, el acceso al objeto remoto es como una
llamada a un mtodo local).
Para localizar un objeto al que se desee acceder, RMI
proporciona un registro que se usa a modo de pginas
amarillas.
Como respuesta de las llamadas a mtodos de un objeto
remoto, RMI devuelve objetos y se encarga de obtener los
bytecodes que sean necesarios (cuando se obtiene una
referencia a un objeto cuyos bytecodes no estn disponibles
en la mquina virtual del receptor).

Distribucin

- 18 -

Fernando Berzal

En RMI:
El servidor crea algunos objetos y los hace accesibles a
travs del registro. A continuacin, se queda esperando a
recibir peticiones.
El cliente obtiene una referencia a un objeto remoto (que
est alojado en el servidor) y la utiliza para invocar mtodos
del objeto de forma remota.
Objetos e interfaces remotos
Para que un objeto sea accesible de forma remota, ha de
implementar un interfaz remoto (derivado de java.rmi.Remote)
Cuando una llamada a un mtodo realizada desde el cliente
devuelve un objeto remoto, en vez de obtener una copia del
objeto, se obtiene una referencia al objeto remoto (un stub que
hace de proxy y se comporta igual que el objeto remoto).
Desarrollo de aplicaciones distribuidas con RMI
1. Crear los distintos componentes de la aplicacin, teniendo
en cuenta que, para que a un objeto se pueda acceder de
forma remota con RMI, es necesario que implemente una
interfaz derivada de java.rmi.Remote.
2. Compilar con javac y generar los stubs con rmic.
3. Hacer accesibles los objetos remotos (usualmente, dejando
los bytecodes correspondientes a los interfaces remotos y a
los stubs en algn servidor web).
4. Arrancar la aplicacin, que incluye el registro RMI, el
servidor y el cliente.
Distribucin

- 19 -

Fernando Berzal

Ejemplo: Plataforma distribuida de cmputo

El servidor RMI

1. Interfaz remota
Para los objetos a los que se acceder de forma remota:

import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Compute extends Remote
{
Object executeTask(Task t)
throws RemoteException;
}

2. Objetos serializables
Aqullos que se transmitirn a travs de la red:

import java.io.Serializable;
public interface Task extends Serializable {
Object execute();
}

Distribucin

- 20 -

Fernando Berzal

3. Implementacin del servidor


import java.rmi.*;
import java.rmi.server.*;
public class ComputeEngine
extends UnicastRemoteObject
implements Compute
{
public ComputeEngine()
throws RemoteException
{
super();
}

// Objeto remoto
// Interfaz remota

public Object executeTask (Task t)


{
return t.execute();
}
// Programa principal
public static void main(String[] args)
throws Exception
{
System.setSecurityManager
(new RMISecurityManager());
String name = "//elvex.ugr.es/Compute";
Compute engine = new ComputeEngine();
Naming.rebind(name, engine);
}
}

El SecurityManager se encarga de controlar las acciones


realizadas por el cdigo que se descarga a travs de la red
(si no creamos uno, no se podr descargar cdigo remoto).
Naming.rebind() registra un objeto para que se pueda

acceder a l de forma remota a travs de una URL.


Mientras que exista alguna referencia a ese objeto (aunque
sea la del registro), el servidor no finalizar su ejecucin.
Distribucin

- 21 -

Fernando Berzal

El cliente RMI
import java.rmi.*;
import java.math.*;
public class ComputePi {
public static void main(String args[])
{
System.setSecurityManager
(new RMISecurityManager());
String name = "//" + args[0] + "/Compute";
Compute comp = (Compute) Naming.lookup(name);

tarea = new XTask();


resultado = (XResult) comp.executeTask(task);
System.out.println(resultado);
}
}

NOTA
La caracterstica ms destacable de RMI es que el servidor no
tiene por qu disponer de antemano de los bytecodes asociados a
la tarea que ha de ejecutar.
Cuando recibe la peticin del cliente, carga los bytecodes en su
mquina virtual, ejecuta la tarea y devuelve el resultado.

Distribucin

- 22 -

Fernando Berzal

Extensiones de RMI: Jini

Jini est montado sobre RMI


y permite descubrir dinmicamente
qu dispositivos y servicios estn
disponibles en la red, sin tener que
saber de antemano su localizacin
exacta (plug & play).

Alternativas a RMI: CORBA y .NET Remoting


CORBA
RMI se puede interpretar como una versin simplificada de
CORBA (un estndar complejo que permite la implementacin de
sistemas distribuidos basados en objetos, independientemente del
lenguaje de programacin que se utilice para implementar las
distintas partes del sistema).
NOTA: RMI slo puede utilizarse en Java, por lo que no sirve para
conectar una aplicacin Java a un sistema no escrito en Java.
.NET Remoting
La plataforma .NET (la alternativa de Microsoft a Java), incluye
un mecanismo similar a RMI que se denomina .NET Remoting.
Ms informacin en
http://elvex.ugr.es/decsai/csharp/distributed/remoting.xml
Distribucin

- 23 -

Fernando Berzal

Ms informacin
Essentials of the Java Programming Language, Part 2
Sockets Communications
http://java.sun.com/developer/onlineTraining/Programming
/BasicJava2/socket.html
The JavaTM Tutorial
Custom Networking: All about sockets
http://java.sun.com/docs/books/tutorial/networking/
The JavaTM Tutorial
RMI
http://java.sun.com/docs/books/tutorial/rmi/

Distribucin

- 24 -

Fernando Berzal

Examen parcial Convocatoria de febrero de 2005


FUNDAMENTOS DE LA PROGRAMACIN
Nombre, apellidos y DNI

____________________________________________________
EJERCICIO 1 (2 puntos)
Defina adecuadamente las clases en Java que se derivan del siguiente diagrama de clases UML
(declare las variables de instancia necesarias para representar los objetos de las distintas clases
que aparecen en el diagrama).

Dada una clase Vector declarada de la siguiente forma


public class Vector
{
private double datos[];
}

EJERCICIO 2 (3 puntos)
Escriba un mtodo eliminarRepetidos() para la clase Vector que elimine los datos que
aparecen repetidos en el vector. Esto es, dado el vector {1,3,2,2,1,3}, el vector debe
quedarse en {1,3,2} tras la llamada al mtodo eliminarRepetidos().
EJERCICIO 3 (2 puntos)
Disee e implemente un mtodo que ordene los datos de mayor a menor valor absoluto. Por
ejemplo, el vector {0,3,-4,2,-1} quedar ordenado como sigue: {-4,3,2,-1,0}.
EJERCICIO 4 (3 puntos)
Se tiene el siguiente mtodo recursivo para la clase Vector:
void in (int j, int k)
{
double aux;
if (j<k) {
in (j+1, k-1);
aux = datos[j];
datos[j] = datos[k];
datos[k] = aux;
}
}

a) Dado un vector v cualquiera y dos nmeros enteros (a, b), qu funcin realiza la
llamada al mtodo recursivo v.in(a,b)? Ejecute paso a paso la llamada al mtodo
vector.in(2,6) para el vector {1,3,5,7,9,11,13,15}.
b) Implemente un mtodo equivalente sin utilizar recursividad.

Examen final Convocatoria de junio de 2005


FUNDAMENTOS DE LA PROGRAMACIN
Nombre, apellidos y DNI

____________________________________________________

PRIMERA PARTE
Consideremos que una imagen est formada por una matriz de nmeros enteros en la que cada
elemento contiene el nivel de gris de un pxel. Este valor puede ir de 0 (negro) a 255 (blanco).
Dada la clase Imagen declarada de la siguiente forma
public class Imagen
{
private int pixels[][];
}

EJERCICIO 1 (3 puntos)
Implemente un mtodo histograma() para la clase Imagen que nos devuelva un vector de
256 elementos en el que su elemento i-simo indica el nmero de pxeles que aparecen en la
imagen con el nivel de gris i.

EJERCICIO 2 (3 puntos)
Disee e implemente un mtodo imagenReducida() que, dada una imagen de tamao NN,
devuelva una nueva imagen de tamao N/2N/2. Cada pxel de la imagen reducida se obtiene
haciendo la media de 4 pxeles adyacentes en la imagen original.
EJERCICIO 3 (4 puntos)
Se tiene el siguiente mtodo recursivo para la clase Imagen:
public void ref (int pos)
{
int aux[];
int N = pixels.length;
if (2*pos<N) {
aux = pixels[N-pos-1];
pixels[N-pos-1] = pixels[pos];
pixels[pos] = aux;
ref(pos+1);
}
}

a) Dado una imagen cualquiera i, qu operacin realiza sobre la imagen la llamada al


mtodo recursivo i.ref(0)? En general, qu hace la llamada al mtodo i.ref(k)
donde k es un valor entero positivo?
b) Implemente un mtodo equivalente sin utilizar recursividad.

Examen final Convocatoria de junio de 2005


FUNDAMENTOS DE LA PROGRAMACIN
Nombre, apellidos y DNI

____________________________________________________

SEGUNDA PARTE

EJERCICIO 1

(2 puntos)

Disee un conjunto de casos de prueba adecuado para comprobar el funcionamiento de


un mtodo encargado de calcular el rea de un tringulo rectngulo dadas las longitudes
de sus tres lados (esto es, las longitudes de sus catetos y de su hipotenusa).
Construya una tabla de casos de prueba de la siguiente forma:
Lado A
3

EJERCICIO 2

Lado B
4

Lado C
5

rea
6

Justificacin
Tringulo rectngulo tpico

(4 puntos)

Declare e implemente adecuadamente las clases en Java que se derivan del siguiente
diagrama de clases UML e implemente el constructor de la clase PuertaTemporizada:

NOTA: El constructor de la clase PuertaTemporizada ha de registrar la puerta en el


temporizador que reciba como parmetro.
EJERCICIO 3

(4 puntos)

Disee e implemente un programa en Java llamado CodificadorDiferencial que sea


capaz de conectarse al puerto TCP 123 del servidor telecos.ugr.es para leer una
serie de datos (un valor real por lnea de texto) y mostrar por pantalla las diferencias
existentes entre los valores recibidos de forma consecutiva.
Por ejemplo, dada la secuencia de valores de entrada (1, 2, 4, 8, 1, 3.6, 6, 6.9,
0.7), el programa debe generar la siguiente secuencia de valores de salida: (1, 1, 2,
4, -7, 2.6, 2.4, 0.9, -6.2).

Examen parcial Convocatoria de junio de 2005


FUNDAMENTOS DE LA PROGRAMACIN
Nombre, apellidos y DNI

____________________________________________________

EJERCICIO 1

(1.5 puntos)

Disee un conjunto de casos de prueba adecuado para comprobar el funcionamiento de


un mtodo encargado de calcular la duracin de una llamada telefnica.
EJERCICIO 2

(2.5 puntos)

Declare adecuadamente las clases en Java que se derivan del siguiente diagrama de
clases UML:

EJERCICIO 3

(3 puntos)

Disee e implemente un programa en Java capaz de leer una serie de datos almacenada
en un fichero de texto y mostrar los dos valores ms altos incluidos en el fichero. Por
ejemplo, dado un fichero con el conjunto de datos (1, 2, 4, 8, 1, 3, 6, 9, 0,
7), el programa debe indicar que los dos valores ms altos son el 9 y el 8.
NOTA: Cada lnea del fichero de texto contiene un nico valor.
EJERCICIO 4

(3 puntos)

Implemente un servidor TCP que nos permita acceder de forma remota a los datos
medidos por un Sensor. El servidor recibir peticiones a travs del puerto 2206.
El servidor deber atender cada peticin en una hebra independiente, de forma que
varios clientes puedan consultar simultneamente los datos medidos por el sensor.
Otros miembros de nuestro equipo de trabajo ya se han encargado de disear e
implementar el protocolo de comunicacin necesario, por lo que nosotros slo tenemos
que delegar en el mtodo atenderCliente cada vez que alguien se conecte a nuestro
servidor:
public class ProtocoloSensor
{
public void atenderCliente (InputStream entrada, OutputStream salida)

donde entrada corresponde al stream mediante el que el servidor recibe datos y salida
representa el stream utilizado para enviar datos desde el servidor hasta el cliente.

Examen parcial Convocatoria de junio de 2005


FUNDAMENTOS DE LA PROGRAMACIN

EJERCICIO 1

(1.5 puntos)

Disee un conjunto de casos de prueba adecuado para comprobar el funcionamiento de un


mtodo encargado de calcular la duracin de una llamada telefnica.

Entradas

Salida

Comentarios

Hora de inicio

Hora de finalizacin

Duracin de la llamada

Justificacin del caso de uso

09:55:04

09:55:55

00:00:51

Caso base

10:37:34

10:48:24

00:10:50

Cambio de minuto

19:15:32

20:32:40

01:17:08

Cambio de hora

23:55:30 22/6/05

00:10:30 23/6/05

00:10:00

Cambio de da

00:00:00

00:00:00

00:00:00

Llamada nula

10:00:00

09:00:00

Error

Finalizacin antes del


comienzo de la llamada

25:64:98

15:30:45

Error

Hora de inicio incorrecta

15:20:45

25:64:98

Error

Hora final incorrecta

12:54:76

12:76:43

Error

Entradas incorrectas

Examen parcial Convocatoria de junio de 2005


FUNDAMENTOS DE LA PROGRAMACIN

EJERCICIO 2

(2.5 puntos)

Declare adecuadamente las clases en Java que se derivan del siguiente diagrama de clases
UML:

public interface Transmisor


{
// ...
}

public abstract class Receptor


{
Transmisor transmisor;
// ...
}

public class Radio extends Receptor implements Transmisor


{
// ...
}

public class TV extends Receptor


{
// ...
}

Examen parcial Convocatoria de junio de 2005


FUNDAMENTOS DE LA PROGRAMACIN

EJERCICIO 3

(3 puntos)

Disee e implemente un programa en Java capaz de leer una serie de datos almacenada en
un fichero de texto y mostrar los dos valores ms altos incluidos en el fichero. Por ejemplo,
dado un fichero con el conjunto de datos (1, 2, 4, 8, 1, 3, 6, 9, 0, 7), el programa
debe indicar que los dos valores ms altos son el 9 y el 8.
NOTA: Cada lnea del fichero de texto contiene un nico valor.
Solucin A: Implementacin modular
import java.io.*;

// Programa principal
public class DosMayoresModular
{
public static void main (String[] args)
throws IOException
{
Serie serie;
// Serie de datos
int
mayores[]; // Valores ms altos
if (args.length<1) {
System.err.println("USO:");
System.err.println();
System.err.println(" java DosMayores <fichero>");
System.err.println();
System.err.println("donde <fichero> es el nombre del fichero
+ que contiene la serie de datos");
System.exit(-1);
}
serie = new Serie(args[0]);
mayores = serie.mayores();

if (mayores!=null) {
if (mayores.length==2) {
System.out.println("Los valores ms altos del fichero son "
+ mayores[0] + " y " + mayores[1]);
} else {
System.out.println("El fichero slo contiene el valor "
+ mayores[0]);
}
} else {
System.out.println("El fichero no contiene valores numricos");
}
}
}

Examen parcial Convocatoria de junio de 2005


FUNDAMENTOS DE LA PROGRAMACIN
// Serie de datos almacenada en un fichero
public class Serie
{
String fichero;
public Serie (String fichero)
{
this.fichero = fichero;
}
public int[] mayores ()
throws IOException
{
FileReader
file;
//
BufferedReader lector;
String
line;
int
total;
int
valor;
int
max1;
int
max2;
file
lector

Lector asociado al fichero


// Lectura lnea a lnea
// Lnea del fichero
// Nmero de valores del fichero
// Valor ledo del fichero
// Mayor valor
// Segundo valor mayor

= new FileReader(fichero);
= new BufferedReader(file);

total = 0;
max1 = Integer.MIN_VALUE;
max2 = Integer.MIN_VALUE;
line = lector.readLine();
while (line!=null) {
try {
valor = Integer.parseInt(line);
total++;
if (valor>max1) {
max2 = max1;
max1 = valor;

// El antiguo mximo
// pasa a ser el segundo mayor valor

} else if (valor>max2) {
max2 = valor;
}
} catch (Exception error) {
// Pasar a la siguiente lnea (nmero incorrecto)
}
line = lector.readLine();
}
if (total>2) {
return new int[] { max1, max2 };
} else if (total==1) {
return new int[] { max1 };
} else {
return null;
}
}
}

Examen parcial Convocatoria de junio de 2005


FUNDAMENTOS DE LA PROGRAMACIN
Solucin B: Implementacin monoltica
import java.io.*;
public class DosMayores
{
public static void main (String[] args)
throws IOException
{
FileReader
fichero;
// Lector asociado al fichero
BufferedReader lector;
// Lectura lnea a lnea
String
line;
// Lnea del fichero
int
total;
// Nmero de valores del fichero
int
valor;
// Valor ledo del fichero
int
max1;
// Mayor valor
int
max2;
// Segundo valor mayor
fichero = new FileReader(args[0]);
lector = new BufferedReader(fichero);
total = 0;
max1 = Integer.MIN_VALUE;
max2 = Integer.MIN_VALUE;
line = lector.readLine();
while (line!=null) {
try {
valor = Integer.parseInt(line);
total++;
if (valor>max1) {
max2 = max1;
max1 = valor;

// NOTA: El antiguo mximo


// pasa a ser el segundo mayor valor

} else if (valor>max2) {
max2 = valor;
}
} catch (Exception error) {
// Pasar a la siguiente lnea
}
line = lector.readLine();
}

if (total>2) {
System.out.println("Los valores ms altos del fichero son "
+max1+" y "+max2);
} else if (total==1) {
System.out.println("El fichero slo contiene el valor "+max1);
} else {
System.out.println("El fichero no contiene valores numricos");
}
}
}

Examen parcial Convocatoria de junio de 2005


FUNDAMENTOS DE LA PROGRAMACIN
EJERCICIO 4

(3 puntos)

Implemente un servidor TCP que nos permita acceder de forma remota a los datos medidos
por un Sensor. El servidor recibir peticiones a travs del puerto 2206.
El servidor deber atender cada peticin en una hebra independiente, de forma que varios
clientes puedan consultar simultneamente los datos medidos por el sensor.
Otros miembros de nuestro equipo de trabajo ya se han encargado de disear e implementar
el protocolo de comunicacin necesario, por lo que nosotros slo tenemos que delegar en el
mtodo atenderCliente cada vez que alguien se conecte a nuestro servidor:
public class ProtocoloSensor
{
public void atenderCliente (InputStream entrada, OutputStream salida)

donde entrada corresponde al stream mediante el que el servidor recibe datos y salida
representa el stream utilizado para enviar datos desde el servidor hasta el cliente.

public class Servidor


{
public static void main (String args[]) throws IOException
{
ServerSocket servidor;
Socket
cliente;
HebraServidor hebra;
servidor = new ServerSocket(2206);
while (true) {

// OJO! Bucle infinito

cliente = servidor.accept();
hebra = new HebraServidor(cliente);
hebra.start();
}
}
}
class HebraServidor extends Thread
{
Socket socket;
public HebraServidor (Socket socket)
{
this.socket = socket;
}
public void run()
{
ProtocoloSensor protocolo = new ProtocoloSensor();
try {
protocolo.atenderCliente ( socket.getInputStream(),
socket.getOutputStream());
} catch (IOException error) {
}
}
}

Convocatoria extraordinaria de septiembre de 2005


FUNDAMENTOS DE LA PROGRAMACIN
Nombre, apellidos y DNI

____________________________________________________

EJERCICIO 1 (3 puntos)
Dada una clase Vector declarada de la siguiente forma
public class Vector
{
private double datos[];
}

escriba un nico mtodo obtenerResumen() para la clase Vector que devuelva el


mnimo, el mximo, la media, la mediana y la moda de los valores incluidos en el vector.
NOTA: Devolver un valor no es mostrarlo por pantalla.
EJERCICIO 2 (2 puntos)
Se tiene el siguiente mtodo recursivo para la clase Vector:
public void rec (int pos)
{
int
i,m;
double x;
if (pos<datos.length) {
m = pos;
for (i=pos+1; i<datos.length; i++)
if (datos[i]>datos[m])
m = i;
x = datos[pos];
datos[pos] = datos[m];
datos[m] = x;
rec(pos+1);
}
}

a) Qu funcin realiza la llamada al mtodo rec(0)?


b) Implemente un mtodo equivalente sin utilizar recursividad.
c) Disee un conjunto completo de casos de prueba que nos sirvan para comprobar el
funcionamiento del mtodo anterior. Construya una tabla de casos de prueba de la
siguiente forma:

Vector inicial

Llamada

{1, 2, 3, 4, 5}

rec(0)

Resultado

Justificacin

(el porqu de cada caso de prueba)

Convocatoria extraordinaria de septiembre de 2005


FUNDAMENTOS DE LA PROGRAMACIN
Nombre, apellidos y DNI

____________________________________________________

EJERCICIO 3

(2 puntos)

Declare e implemente adecuadamente las clases en Java que se derivan del siguiente
diagrama de clases UML e implemente el mtodo dibujar() para las clases Ventana y
Panel.

NOTA: Al dibujar una ventana, hay que dibujar su icono y el panel que contiene todos
los componentes grficos incluidos en la ventana. Al dibujar el panel, hay que ir
dibujando uno a uno todos los componentes que contiene.

EJERCICIO 4

(3 puntos)

Disee e implemente un servidor TCP en Java llamado ServidorSimpleDeFicheros


que sea capaz de recibir conexiones a travs del puerto TCP nmero 21.
Cuando un cliente se conecta al servidor, le enva una lnea de texto que contiene el
nombre de un fichero al que desea acceder. Entonces, el servidor lee el fichero que haya
solicitado el cliente y le devuelve el contenido del mismo a travs de la conexin
establecida con el cliente a travs de un socket.
NOTA: Cuando el cliente intenta acceder a un fichero que no existe en el
servidor, el servidor simplemente cierra la conexin sin enviarle nada al cliente.

Examen parcial Convocatoria de febrero de 2006


FUNDAMENTOS DE LA PROGRAMACIN
Nombre, apellidos y DNI

____________________________________________________
EJERCICIO 1 (3 puntos)
Defina adecuadamente las clases en Java que se derivan del siguiente diagrama de clases UML.
Declare todas las variables de instancia necesarias para representar los objetos de las distintas
clases que aparecen en el diagrama y declare (sin implementarlos) todos los mtodos que
considere oportunos.

Dada una clase Matriz declarada de la siguiente forma


public class Matriz
{
private int datos[][];
}

EJERCICIO 2 (4 puntos)
Escriba un mtodo encuentra() para la clase Matriz que, dado un vector de nmeros enteros
que recibe como parmetro, nos indique la posicin dentro de la matriz donde se encuentra el
vector. El vector puede estar oculto dentro de la matriz igual que una palabra en una sopa de
letras: puede aparecer horizontal, vertical o diagonalmente (al derecho y tambin al revs).
EJERCICIO 3 (3 puntos)
Dado el siguiente mtodo recursivo para la clase Matriz, interprete cul es la funcin de la
llamada al mtodo matriz.f(a,b) siendo a<=b e implemente un mtodo equivalente sin
utilizar recursividad. Se le ocurre alguna aplicacin de la llamada matriz.f(1,9)?
public boolean f (int a, int b)
{
if (a==b)
return g(a);
else
return g(a) && f(a+1,b);
}
private boolean g (int x)
{
int i,j;
for (i=0; i<datos.length; i++)
for (j=0; j<datos[i].length; j++)
if (datos[i][j] == x)
return true;
return false;
}

Examen parcial Convocatoria de febrero de 2006


FUNDAMENTOS DE LA PROGRAMACIN

EJERCICIO 1
Defina adecuadamente las clases en Java que se derivan del siguiente diagrama de clases
UML. Declare todas las variables de instancia necesarias para representar los objetos de las
distintas clases que aparecen en el diagrama y declare (sin implementarlos) todos los
mtodos que considere oportunos.

class JDBCConnectionPool
{
public Connection getConnection ()
{}
public void returnConnection (Connection connection)
{ }
}
class JDBCDatabase
{
public Connection getConnection ()
{}
public void closeConnection (Connection connection)
{}
}

Examen parcial Convocatoria de febrero de 2006


FUNDAMENTOS DE LA PROGRAMACIN
class Dataset
{
private boolean sequentialAccess;
private boolean randomAccess;
private DatasetMetadata metadata;
public void open()
{}
public void close()
{}
public Object next()
{}
public int size()
{}
}

class JDBCDataset extends Dataset


{
private JDBCDatabase database;
}

class DatasetMetadata
{
private String id;
private String type;
private Dataset datasets[];
public String getAttribute(String id)
{}
}

class JDBCDatasetMetadata extends DatasetMetadata


{
}

Examen parcial Convocatoria de febrero de 2006


FUNDAMENTOS DE LA PROGRAMACIN
EJERCICIO 2
Escriba un mtodo encuentra() para la clase Matriz que, dado un vector de nmeros
enteros que recibe como parmetro, nos indique la posicin dentro de la matriz donde se
encuentra el vector. El vector puede estar oculto dentro de la matriz igual que una palabra
en una sopa de letras: puede aparecer horizontal, vertical o diagonalmente (al derecho y
tambin al revs).
public class Matriz
{
private int datos[][];

public int[] encuentra (int vector[])


{
int i,j;
int pos[] = new int[2];
pos[0] = -1;
pos[1] = -1;
for (i=0; i<datos.length; i++) {
for (j=0; j<datos.length; j++) {
if (encuentraPos3(vector,i,j)) {
pos[0] = i;
pos[1] = j;
}
}
}
return pos;
}
private boolean encuentraPos (int vector[], int x, int y)
{
int
dx,dy;
boolean encontrado = false;
for (dx=-1; dx<=1; dx++) {
for (dy=-1; dy<=1; dy++) {
if (encuentraDir(vector,x,y,dx,dy)) {
encontrado = true;
}
}
}
return encontrado;
}

Examen parcial Convocatoria de febrero de 2006


FUNDAMENTOS DE LA PROGRAMACIN

private boolean encuentraDir


(int vector[], int x, int y, int dx, int dy)
{
int
k, px, py;
boolean ok = true;
px = x;
py = y;
for (k=0; k<vector.length; k++) {
if ( (px>=0) && (px<datos.length)
&& (py>=0) && (py<datos[0].length)) {
if (datos[px][py]!=vector[k])
ok = false;
} else {
ok = false;
}
px += dx;
py += dy;
}
return ok;
}

Variantes y mejoras
1. Eliminacin de algunas iteraciones innecesarias:
encuentra
for ... && (pos[0]==-1) ...
encuentraPos
for ... && !encontrado ...
encuentraDir
for ... && ok ...

Examen parcial Convocatoria de febrero de 2006


FUNDAMENTOS DE LA PROGRAMACIN
2. Reduccin del nmero de comprobaciones en encuentraDir
private boolean encuentraDir2
(int vector[], int x, int y, int dx, int dy)
{
int
k, px, py;
int
finx, finy;
boolean ok = true;
finx = x + (vector.length-1)*dx;
finy = y + (vector.length-1)*dy;
if ( (finx>=0) && (finx<datos.length)
&& (finy>=0) && (finy<datos[0].length)) {
px = x;
py = y;
for (k=0; k<vector.length; k++) {
if (datos[px][py]!=vector[k])
ok = false;
px += dx;
py += dy;
}
} else {
ok = false;
}
return ok;
}

3. Implementacin alternativa de encuentraPos


private boolean encuentraPos2 (int vector[], int x, int y)
{
return encuentraDir(vector,x,y, 1, 0)
|| encuentraDir(vector,x,y,-1, 0)
|| encuentraDir(vector,x,y, 0, 1)
|| encuentraDir(vector,x,y, 0,-1)
|| encuentraDir(vector,x,y, 1, 1)
|| encuentraDir(vector,x,y, 1,-1)
|| encuentraDir(vector,x,y,-1, 1)
|| encuentraDir(vector,x,y,-1,-1);
}

Examen parcial Convocatoria de febrero de 2006


FUNDAMENTOS DE LA PROGRAMACIN

4. Por fuerza bruta (en las 8 direcciones)


private boolean encuentraPos3 (int vector[], int x, int y)
{
int
k;
boolean encontrado;

encontrado = true;
for (k=0; k<vector.length; k++)
if ( (x+k>=datos.length) || (datos[x+k][y]!=vector[k]) )
encontrado = false;

if (!encontrado) {
encontrado = true;
for (k=0; k<vector.length; k++)
if ( (x-k<0) || (datos[x-k][y]!=vector[k]) )
encontrado = false;
}

if (!encontrado) {
encontrado = true;
for (k=0; k<vector.length; k++)
if ( (y+k>=datos[0].length) || (datos[x][y+k]!=vector[k]) )
encontrado = false;
}

if (!encontrado) {
encontrado = true;
for (k=0; k<vector.length; k++)
if ( (y-k<0) || (datos[x][y-k]!=vector[k]) )
encontrado = false;
}

Examen parcial Convocatoria de febrero de 2006


FUNDAMENTOS DE LA PROGRAMACIN

// Diagonales

if (!encontrado) {
encontrado = true;
for (k=0; k<vector.length; k++)
if ( (x+k>=datos.length) || (y+k>=datos[0].length)
|| (datos[x+k][y+k]!=vector[k]) )
encontrado = false;
}

if (!encontrado) {
encontrado = true;
for (k=0; k<vector.length; k++)
if ( (x+k>=datos.length) || (y-k<0)
|| (datos[x+k][y-k]!= vector[k]) )
encontrado = false;
}

if (!encontrado) {
encontrado = true;
for (k=0; k<vector.length; k++)
if ( (x-k<0) || (y+k>=datos[0].length)
|| (datos[x-k][y+k]!=vector[k]) )
encontrado = false;
}

if (!encontrado) {
encontrado = true;
for (k=0; k<vector.length; k++)
if ( (x-k<0) || (y-k<0)
|| (datos[x-k][y-k]!=vector[k]) )
encontrado = false;
}

return encontrado;

Examen parcial Convocatoria de febrero de 2006


FUNDAMENTOS DE LA PROGRAMACIN
EJERCICIO 3
public boolean f (int a, int b)
{
if (a==b)
return g(a);
else
return g(a) && f(a+1,b);
}
private boolean g (int x)
{
int i,j;
for (i=0; i<datos.length; i++)
for (j=0; j<datos[i].length; j++)
if (datos[i][j] == x)
return true;
return false;
}

Versin iterativa
public boolean fwhile (int a, int b)
{
boolean resultado = true;
while (a<=b) {
resultado = resultado && g(a);
a++;
}
return resultado;
}
public boolean ffor (int a, int b)
{
int x;
boolean resultado = true;
for (x=a; (x<=b) && resultado; x++)
resultado = g(x);
return resultado;
}

Examen final Convocatoria de junio de 2006


FUNDAMENTOS DE LA PROGRAMACIN
Nombre, apellidos y DNI

____________________________________________________
PRIMERA PARTE
Consideremos que una imagen est formada por una matriz de nmeros enteros en la que cada
elemento contiene el nivel de gris de un pxel. Este valor puede ir de 0 (negro) a 255 (blanco).
Dada la clase Imagen
public class Imagen
{
private int pixels[][];
}

EJERCICIO 1 (2 puntos)
Implemente un mtodo reflejoHorizontal()que refleje horizontalmente la imagen (esto es,
lo que hubiese a la izquierda de la imagen original debe quedar a la derecha y lo que hubiese a
la derecha debe quedar a la izquierda en la imagen reflejada).
EJERCICIO 2 (4 puntos)
Disee e implemente un mtodo ecualizar() que ecualice la imagen. La ecualizacin del
histograma de una imagen uniformiza los niveles de gris de una imagen de tal forma que, en
imgenes muy concentradas en determinados niveles de gris, se aumenta el contraste. Para
ecualizar una imagen:
1. Se calcula el histograma acumulado de la imagen: c(i ) =

p( j )
j =0

2. Se transforma cada pxel de la imagen de tal forma que, si tenemos un pxel con
el nivel de gris i, ste pasar a tener el nivel de gris 255 * c(i) / pxeles,
donde p(j) es el nmero de pxeles de la imagen con el nivel de gris j, c(i) es el nmero de
pxeles con una intensidad menor o igual que i y pxeles es el nmero de pxeles de la imagen.
EJERCICIO 3 (4 puntos)
Dado el siguiente fragmento de cdigo:
static final double N = 2;
static final double PREC = 1e-6;
static double f (double x)
{
return x*x-N;
}
static double bis (double min, double max)
{
double med = (min+max)/2;
if (max-min<PREC) {
return med;
} else if (f(min)*f(med)<0) {
return bis (min,med);
} else {
return bis (med,max);
}
}

a) Qu calcula la llamada a la funcin recursiva bis(0,N)? Si cambiamos el valor


de N, qu estaramos calculando? Y si cambisemos la funcin f(x)?
b) Implemente un algoritmo iterativo equivalente.

Examen final Convocatoria de junio de 2006


FUNDAMENTOS DE LA PROGRAMACIN
Nombre, apellidos y DNI

____________________________________________________
SEGUNDA PARTE
EJERCICIO 1 (4 puntos)
Dado el siguiente diagrama UML:

a) Declare e implemente adecuadamente en Java las clases que se derivan del diagrama.
b) Defina una subclase de TMinerTask llamada Experimento que redefina el mtodo
execute() de tal forma que ste sirva para determinar si un nmero es primo o no (el
nmero se obtiene a travs del mtodo getInput(), el cual devuelve un String, y el
resultado del experimento se guarda como una cadena utilizando el mtodo setOutput())
c) Disee un conjunto de casos de prueba adecuado para comprobar el funcionamiento de la
clase implementada en el apartado anterior.
d) Implemente un programa en Java que lance el experimento en una hebra independiente.

EJERCICIO 2 (3 puntos)
Disee e implemente un programa en Java que lea un fichero de texto y nos d la frecuencia de
las 3 vocales que aparecen ms a menudo en el fichero.

EJERCICIO 3 (3 puntos)
Queremos acceder a un componente de tipo TMinerComponent de forma remota usando RMI:
describa cmo deberamos declarar la clase TMinerComponent, implemente el servidor RMI
necesario para poder acceder al componente de forma remota y escriba el cdigo necesario para
acceder al componente desde un cliente RMI.

Examen parcial Convocatoria de junio de 2006


FUNDAMENTOS DE LA PROGRAMACIN
Nombre, apellidos y DNI

____________________________________________________

EJERCICIO 1

(4 puntos)

Dado el siguiente diagrama de clases UML:


a) Declare e implemente en Java las clases que se derivan del diagrama de clases.
b) Implemente los mtodos notificar() y registrar() de la clase Sujeto (el
mtodo notificar() se encarga de enviar mensajes de actualizacin a todos los
observadores asociados al sujeto observado, mientras que registrar() aade un
nuevo observador al conjunto de observadores asociados al sujeto observado).
c) Describa cmo resolvera el problema mostrado en el diagrama anterior si no
hubisemos podido utilizar herencia mltiple. Dibuje un diagrama UML con el
diseo resultante.
EJERCICIO 2

(2 puntos)

Implemente un mtodo que, dada una cadena de caracteres, nos indique si la cadena
incluye una subcadena que tambin recibe como parmetro.
Disee un conjunto de casos de prueba adecuado para comprobar el funcionamiento del
mtodo anterior y construya una tabla de casos de prueba de la siguiente forma:
Cadena

EJERCICIO 3

Subcadena

Resultado

Justificacin

(4 puntos)

Utilizando el mtodo del ejercicio anterior, disee e implemente un programa en Java


llamado Filtro que sea capaz de conectarse al puerto TCP 80 del servidor
telecos.ugr.es para leer un texto (esto es, una secuencia de cadenas de texto) y
almacene en un fichero todas las lneas que incluyan una palabra que el programa recibe
como parmetro.

Convocatoria extraordinaria de septiembre de 2006


FUNDAMENTOS DE LA PROGRAMACIN
Nombre, apellidos y DNI

____________________________________________________

EJERCICIO 1 (3 puntos)
El nmero de Reynolds es un nmero adimensional utilizado en mecnica de fluidos que viene
dado por la siguiente expresin:

donde es la densidad del fluido, vs la velocidad caracterstica del fluido, L la longitud


caracterstica del problema (p.ej. el dimetro de una tubera) y la viscosidad del fluido.
Si el nmero de Reynolds es menor que 2100 el flujo es laminar. Si es mayor de 4000, el flujo
es turbulento.
a) Implemente una clase que permita representar las caractersticas de un problema de
mecnica de fluidos e incluya un mtodo que nos devuelva si el flujo de un fluido tiene
carcter laminar o turbulento.
b) Disee un conjunto completo de casos de prueba que nos sirva para comprobar el
funcionamiento del mtodo anterior. Construya una tabla de casos de prueba de la
siguiente forma:
vs

Resultado

Justificacin
(el porqu de cada caso de prueba)

EJERCICIO 2 (2 puntos)
Dada una clase Vector declarada de la siguiente forma:
public class Vector
{
private int datos[];
public int size ()
{
return datos.length;
}
public int rec (int j, int k)
{
int m = (j+k)/2;
if (j<=k) {
return (datos[m]%2)
+ rec(j, m-1)
+ rec(m+1, k);
} else {
return 0;
}
}
}

Convocatoria extraordinaria de septiembre de 2006


FUNDAMENTOS DE LA PROGRAMACIN
Nombre, apellidos y DNI

____________________________________________________

a) Qu funcin realiza la llamada al mtodo vector.rec(0,vector.size()-1)? Y


la llamada a vector.rec(a,b) para dos valores cualesquiera a y b?
b) Implemente un mtodo equivalente sin utilizar recursividad.

EJERCICIO 3

(2 puntos)

Declare e implemente adecuadamente las clases en Java que se derivan del siguiente
diagrama de clases UML:

EJERCICIO 4

(3 puntos)

Disee e implemente en Java un servidor TCP multihebra que sea capaz de recibir
conexiones a travs del puerto TCP nmero 21.
Cuando un cliente se conecta al servidor, le enva una lnea de texto que contiene el
nombre de un fichero al que desea acceder. Entonces, el servidor lee el fichero que haya
solicitado el cliente y le devuelve el contenido del mismo a travs de la conexin
establecida con el cliente a travs de un socket.
NOTA: Cuando el cliente intenta acceder a un fichero que no existe en el
servidor, el servidor simplemente cierra la conexin sin enviarle nada al cliente.

Вам также может понравиться