Está en la página 1de 54

3.

1 Introducción a
Capítulo III TDA y OO
Tipos de Datos Abstractos,
Orientación a Objetos y
Lenguaje Java

Problemas en el Desarrollo de Modularidad y Reutilización del


Grandes Programas Software (1/2)
Œ ¿Cómo organizar una pieza de software, de l Ideas:
manera que sea fácil de mantener y l Organizar el programa en grupos de
administrar? subprogramas y datos, lógicamente relacionados,
denominados módulos.
• ¿Cómo evitar tener que recompilar todo un
l Agrupar en subprogramas que puedan ser
sistema, en vista de un pequeño cambio?
compilados de forma independiente, sin
necesidad de recompilar todo el sistema.

Modularidad y Reutilización del


Software (2/2) Encapsulación
l El proceso de diseñar los módulos o l Encapsulación: Agrupar un conjunto de
contenedores sintácticos, se denomina subprogramas junto con los datos que ellos
modularización. manipulan.
l Una unidad de compilación es un conjunto de l La encapsulación permite resolver los dos
subprogramas que pueden compilarse de problemas presentados.
manera independiente al resto del sistema l Además permite ver los conjuntos como
cajas negras.

1
Ventajas de la Encapsulación Tipos de Datos Abstractos (TDAs)
l Mayor modularidad l Un TDA, corresponde a una encapsulación
l Mejor mantención que incluye:
l Permite ser movido l La representación de un tipo de dato específico
l Ocultamiento de la información l Las operaciones asociadas a ese tipo
l Un objeto provee una interfaz para comunicarse l Una instancia de un TDA se denomina objeto
con él y abstrae de los detalles de
implementación
l Cambios en la información y métodos internos no
afectan a otros objetos

Ejemplo: Ocultamiento de la
Ocultamiento de Información Información

l Mediante control de acceso, detalles public class PruebaUsoStack {


innecesarios de la implementación de un
public static void main(String[] args) {
TDA se ocultan a aquellas unidades fuera de Stack st = new Stack(5);
la encapsulación
st.push ("Hola");
l Un cliente es una unidad de programa que st.push(args[0]);
String s;
hace uso de una instancia de TDA while (st.size()>0) {
s = st.pop();
System.out.println(s);
}
}
}

Problemas de Reuso con TDAs OO en el Diseño de Lenguajes


l OO Puros (e.g. Smalltalk)
l Los TDAs son las unidades a reusar, pero:
l Generalmente requieren ser adaptadas para el l OO no puros
nuevo uso l mantienen elementos de otros paradigma (e.g.
l Hacer las modificaciones implicaría entender los Java y Eiffel de los imperativos)
detalles de implementación del TDA reutilizado l Lenguajes Extendidos a OO
l ¿Cómo representar relaciones entre distintos l Extensión de imperativo (e.g. C++ y Ada 95)
TDAs ? l Extensión de funcional (e.g. CLOS)
l Por ejemplo: relación padre -hijo (relación de
subordinación) o de similitud de roles

2
Soporte para Programación
Visión Computacional OO (PURA) Orientada a Objetos
l Un programa es un conjunto de objetos (instancias l Tipos de Datos Abstractos
de alguna clase), que corresponden a una l Clases y Objetos
abstracción del mundo real (problema) l Concepto de encapsulación
l Un objeto se comunica con otro objeto enviando un l Herencia
mensaje a algún método de este último, el cual le l Simple y múltiple
puede retornar otro objeto como resultado
l Polimorfismo, con especie particular de
l Procesamiento del mensaje puede alterar el estado
ligado dinámico de métodos a mensajes
del objeto (sus variables internas).
l Clases y métodos virtuales en C++
l Uso de interfaces en Java

Objetos Objetos (representaciones)


l Un objeto tiene estado y comportamiento
l El estado se mantiene en variables
l El comportamiento se implementa mediante
métodos
l Un objeto encapsula su estado mediante sus
métodos (Abstracción de datos) NombreClase

l Un objeto controla la manipulación de su atributo 1 : Integer


atributo 2 : Integer
estado mediante sus métodos atributo 3 : Boolean

Metodo A()
Metodo B()
Metodo C()

Ejemplo de Objeto: Stack Mensajes


l Objetos interactúan enviándose mensajes
l Un mensaje consiste en:
Método
push() l Identificador del objeto
l Identificador del método
pop()
l Parámetros (si son necesario)
size()
Estado l Objetos no requieren estar en el mismo
proceso o máquina

3
Mensajes Ejemplo de Mensaje

Cliente
Stack S
push(“Hola”)

push()
pop()
size()

1.- Objetos utilizan métodos para enviar mensajes

2.- Los métodos manipulan el estado interno

Ejemplo: Mensajes a un Objeto en Java Concepto de Clase

public class PruebaUsoStack { l Introducidas en SIMULA 67


l Una clase representa a un conjunto de objetos con
public static void main(String[] args) { características comunes
Stack st = new Stack(5);
l Un objeto es una instancia de una clase
st.push ("Hola");
st.push(args[0]); l Una clase es un molde a partir del cual se crean
String s; objetos
while (st.size()>0) { l Una clase puede tener variables (o campos) y
s = st.pop();
System.out.println(s); métodos de clase (comunes para toda la clase)
}
}
}

Clases vs. Objetos Clases: Ejemplo en C++


l Una clase define un tipo abstracto de dato
class complex {
l Los objetos son instancias de una clase, y por lo private :
Datos Campos privados
tanto ocupan memoria. float re, i m;
public :
complex() {
l Se les puede instanciar en forma estática, del stack Constructor re = im = 0 . 0 ;
}
o del heap (C++ permite las tres formas). float getRealPart(); Campos públicos
Operaciones float getImPart();
l Si se crean del heap, su destruccción es explícita o ...

implícita (e.g. C++ es explícita y Java es implícita) }

int main(void ) {
complex cpl; // Crea una instancia de la clase (objeto)
cout << cpl.getRealPart();
...
}

4
Ejemplo: Ejemplo:
Implementación de un Stack en Java Creación de un objeto de clase Stack

public class PruebaUsoStack {


public class Stack { public String pop () {
private int Maximo ; String respuesta = "";
private int top = -1; public static void main(String[] args) {
private String[] buffer; if (top>=0) Stack st = new Stack(5);
respuesta = buffer[top--];
public Stack(int i) { else System.err.println("Oops, stack vacio"); st.push ("Hola");
Maximo = i; return respuesta;
buffer = new String[i ]; st.push(args[0]);
}
} String s;
public int size () { while (st.size()>0) {
public void push(String nuevo) { return top+1;
if (top < Maximo-1) s = st.pop();
}
buffer[++top] = nuevo; System.out.println(s);
else System.err.println("Oops, stack lleno"); } }
}
}
}

Concepto Herencia Jerarquía de Herencia


l Permite reusar tipos de datos abstractos ya l Un TDA se denomina clase, y las que
definidos, sin alterarlos. heredan de una clase base se denominan
l La reutilización se realiza definiendo nuevos clases derivadas (o subclases)
TDA que modifican o agregan (datos y/o l Un TDA se deriva de una clase padre
métodos) al TDA de base.
denominada superclase
l Por lo tanto, permite adaptar un TDA a las l En Java se habla de extender una clase
condiciones particulares de un problema con
menor esfuerzo

Representación de Herencia Ejemplo: Herencia en Java


Usuario
login : String
password : String
Nombre : String public class StackPrint extends Stack { public class Prueba {
claveDB

Alumno getNombre()
Empleado public StackPrint(int i) { public staticvoid main(String[] args) {
curso : Integer login()
sueldo : Integer super(i);
titulo : String
promedio : Single load() } StackPrint stp = new StackPrint (5);
pagarSueldo()
nuevaAnotacion() stp.push("Hola-print ");
nuevaNota() public void print () { stp.push(args[0]);
registrarAsistencia()
rendirPrueba() Profesor System.out.println("tamaño: " + (top+1)); stp.print ();
horas_de_trabajo : Integer Administrativo for (int i=0; i<top+1; i++) {
jefeCurso : String cargo : String
System.out.println(i + ": " + buffer[i]); }
fijarPrueba() marcarTarjeta() }
} }

Secretaria Director Portero }

matricularAlumno() contratarProfesor() limpiarPasillo()

5
Herencia: Relaciones entre
clases Ventajas de la Herencia
l El mecanismo de herencia permite extender l Subclases proveen comportamiento
una clase (agregar variables o métodos) especializado en base a la superclase
l Si B extiende a A, entonces B hereda todo lo l Los programadores pueden definir clases
de A (la superclase), siendo la clase abstractas, que definen un comportamiento
genérico, que debe ser específicamente
heredera B una subclase de A definido por las clases herederas
l Una subclase heredera puede implementar a l En resumen, representan un mecanismo de
su manera un método heredado (override) reutilización de interfaces y código

Herencia Múltiple Problemas con Herencia Múltiple


l Colisión de nombres introduce una
l La nueva clase hereda sus propiedades a
complicación
partir de dos o más clases
l Pérdida de eficiencia por su mayor
complejidad (en el ligado de los métodos)
...
l No está claro que su uso mejore el diseño y
Clases bases
mantención de sistemas, considerando la
mayor complejidad de organización

Subclase

Polimorfismo mediante Ejemplo:


Ligado Dinámico de Métodos Ligado Dinámico de Métodos
l Permite crear variables del tipo de la clase del padre
que pueden referenciar objetos de cualquier Figura
subclase (polimorfismo ) Datos
l Las subclases pueden tener métodos que llevan el dibujar
mismo nombre del padre, pero que las subclases rotar
las adaptan con otra implementación (override)
Triángulo Cuadrado
l Cuando se invoca un método de este tipo, se debe
dinámicamente hacer el ligado al método que Datos Datos
corresponde (dynamic binding). dibujar dibujar
rotar rotar

6
Clases y Métodos Virtuales Polimorfismo en C++
class figura {
l A veces, la jerarquía de clases hace que para una // ...
public:
clase particular, no tenga sentido la creación de virtual void rotar (int) = 0;
virtual void dibujar (void) = 0;
objetos. // ...
};
l En tal caso, la clase puede definir el prototipo de
métodos genéricos que son implementados en class circulo: public figura {
real radio;
todas las clases derivadas. public:
void rotar (int) {} // anula figura::rotar
l Tales métodos se denominan métodos virtuales. void dibujar (void); // anula figura::dibujar
circulo (punto p, real radio);
l La clase que posee estos métodos se denomina clase };
virtual.
l Los métodos virtuales pueden tener una implementación figura *f[100];
...
por defecto. for (int i=0; i<n; i++)
f[n]->dibujar();

Interfaces en Java Ejemplo: Interfaz en Java


l Define un protocolo de comunicación para la
public interface StackInterface { public class StackImp implements StackInterface {
interacción de objetos sin necesidad de void push(String s); private int Maximo;
conocer su clase (especie de polimorfismo) String pop(); protected int top = -1;
int size(); protected String[] buffer;
l Una o más clases pueden implementar una }
public StackImp(int i) {
misma interfaz Maximo = i;
l Una clase que implementa una interfaz debe buffer = new String[i];
}
necesariamente implementar cada método de la // .....
interfaz }

Utilidad de una Interfaz


3.2 Introducción a
l Captura similitudes entre clases no
relacionadas sin forzar artificialmente una Java
relación entre ellas
l Declarar métodos que una o más clases Historia, características, lenguaje
esperan implementar y entorno de Java
l Revelar una interfaz de programación sin
revelar las clases que la implementan

7
Orígenes del Lenguaje Java Tecnología Java
l 1991. James Gosling inicia proyecto para escribir l Lenguaje de Programación
código independiente de plataforma para sistemas l Orientado a objetos
empotrados. Intenta con C++, pero no le satisface
l Sintaxis similar a C++
l 1993. Desarrolla un nuevo lenguaje llamado OAK,
similar a C++, pero portable y seguro l Plataforma
l 1994. Aparece WWW y Mosaic l Máquina Virtual Java (JVM)
l 1995. Sun anuncia disponibilidad de lenguaje Java l Java API
y browser HotJava, que soporta applets l Tres versiones
l 2004. Versión J2se1.5-Beta disponible. Incluye l J2SE
programación genérica como parte del lenguaje l J2EE
l J2ME

Características del Lenguaje


Java Proceso de Desarrollo en Java
l Simple y orientado a objetos
Programa Java Genera
l Simple de aprender, alta reutilización y bibliotecas
bytecode
l Robusto y seguro public class HolaMundoApp {
publicstaticvoid main(String[] args) {

l Tipificación fuerte, recolección de basura // Desplegar "Hola Mundo!"


System.out.println(" Hola Mundo!"); Compilador
}

l Interpretado, neutro de la arquitectura y portable }

l Se compila en bytecode, interpretado por JVM HolaMundoApp.class


HolaMundoApp.java
l Distribuido y alto desempeño
l Movilidad de código y permite tb. compilación JIT
l Multi-hebra
l Mejora la interactividad de la aplicaciones JVM JVM JVM
l Dinámico
Windows Linux
l Permite enlace y carga dinámica de clases Solaris

Un Primer Programa de
Aplicación Java Aplicación
l Le dice al sistema que ejecute la función /**
main de alguna clase * La clase HolaMundoApp implementa una aplicación
* que despliega por la salida estándar “Hola Mundo”
l Carga dinámicamente otras clases que */
requiera
l Aplicaciones son consideradas confiables public class HolaMundoApp {
public static void main(String[] args) {
(no significa que lo sean) // Desplegar "Hola Mundo!"
l Pueden leer, escribir, crear o borrar archivos System.out.println(" Hola Mundo!");
}
}

8
Un Primer Programa de
Aplicación Comentarios en Java
l // texto
l Se ignora el texto hasta el final de la línea (como
C o C++)
l /* texto */
l Se ignora todo texto entre /* y */ (tipo C o C++)
l /** texto */
l Comentarios de documentación (los usa la
herramienta javadoc)

Acceso a Recursos del


Método main Sistema
l Cuando se ejecuta una aplicación Java, el l Java provee una API (Application Programming
interpretador invoca a main Interface) que permite acceder a recursos en forma
independiente del entorno
l Si no existe se genera un error
l E/S, reloj, etc.
l main tiene un argumento único, un arreglo l La API viene definida en el paquete System
de strings
l Permite al ambiente de ejecución pasar
Programa Java
parámetros a la aplicación
l Por ejemplo en la línea de comando System

Entorno de Ejecución

Ejemplo de uso de System Applets


l Significa “aplicacioncita”, que lo diferencia de
class TestNombreUsuario {
public static void main(String[] args) { una aplicación normal
String nombre; l Uso normal es en un Web Browser
nombre = System.getProperty ("user.name");
l También se puede ver con appletviewer
System.out.println(nombre);
} l Proceso de compilación similar al anterior,
} pero diferente modelo de ejecución

9
Modelo de Ejecución del
Applet Programando un Applet
import java.applet.*;
import java.awt.*;
Servidor
Web /**
Browser * la clase HolaMundo implementa una applet que
Œ
* simplemente despliega ”Hola Mundo!".
*/
Applet
Applet public class HolaMundo extends Applet {
public void paint(Graphics g) {
JVM • // Display "Hello World!"
g.drawString (”Hola Mundo!", 50, 25);
}
}

Importación de Clases y
Página Web que Carga Applet Paquetes
<HTML> l La palabra import permite importar clases de
un paquete
<HEAD>
<TITLE>Un Programa Simple con Applet</TITLE> l En el ejemplo import java.applet:* permite utilizar
</HEAD> todas las clases del paquete java.applet
<BODY> l En el ejemplo anterior Applet es una clase del
Aqui viene la salida del programa: paquete java.applet
<APPLET CODE="HolaMundo.class" WIDTH=150 HEIGHT=25>
</APPLET>
</BODY>

</HTML>

Definición de Subclases Implementación de Métodos


l La palabra extends permite definir una l Una clase puede implementar uno o más
subclase a partir de otra (herencia) métodos
l En el ejemplo: l En el ejemplo:
public void paint(Graphics g) {
public class HolaMundo extends Applet { ... g.drawString(”Hola Mundo!", 50, 25);
}
l Un applet, en general, debe implementar al
menos uno de los métodos siguientes
métodos: init, start y paint

10
Funcionalidad de Java (1/2) Funcionalidad de Java (2/2)
l Esencial ....
l Objetos, strings , números, E/S, estructuras de datos,
propiedades del sistema, fecha, hora, etc. l Threads (hebras)

l Interfaces gráficas l Programación con múltiples threads


l AWT, Swing, Java2d y Java3d l Componentes de Software (JavaBean)
l Comunicación en la Red y Applets l Se pueden enchufar en arquitecturas existentes
l Web, URL, sockets UDP y TCP, direcciones IP l Serialización de Objetos
l Internacionalización l Permite persistencia liviana y comunicación via RMI
l Programas pueden adaptarse al lugar e idioma l Acceso uniforme a base datos relaciones
l Seguridad l Usan JDBC (Java Database Connectivity)
l Firma digital, gestión de claves, certificados, control
de acceso, etc.

Java 2 SDK
3.3 Conceptos
Básicos del Lenguaje
Java

Conjunto de Caracteres Identificadores


l Java utiliza Unicode, un conjunto de l Deben comenzar con una letra, incluido _ o
caracteres de 16 bits $, seguido de letras o dígitos
l Java permite leer ASCII de 7-bit o Latin-1, l Letras en Unicode es un concepto más amplio
conviertiéndolo a Unicode l Son válidos: Árbol, Hähnchen, etc.
l Son pocos los editores actuales que soportan l Se diferencia mayúscula de minúscula
Unicode l árbol es diferente a Árbol
l Se puede usar su código en formato \udddd, l Java define algunas palabras reservadas que
donde d es un dígito hexadecimal no pueden ser usadas como identificador

11
Palabras Resevadas
l abstract l double int super
Variables, Constantes
boolean else
l

l break
l

l extends
interface
long
switch
synchronized y Tipos Primitivos
l byte l final native this
l case l finally new throw
package throws
l catch l float
private transient
l char l for
protected try
l class l goto public void
l const l if return volatile
l continue l implements short while
l default l import static
l do l instanceof

Variable Tipos de Datos


l Una variable es un item de datos nombrado l Un tipo define los posibles valores para una variable
por un identificador l Java define dos categorías de tipos de datos:
l Una variable tiene un tipo, que debe ser l Primitivos. Contiene un único valor de tamaño y formato
declarado antes de su uso (como en C) apropiado (e.g. Entero, real, booleano, etc.)
l Referencias. Es una dirección a un conjunto de valores
l tipo variable
(e.g. Arreglo, clase e interfaz)
l Una variable tiene un ámbito (scope), l Las direcciones son implícitas, dado que Java no
definido por la visibilidad que tiene la variable soporta punteros
en el programa

Tipos de Datos Primitivos Más sobre Datos Primitivos


Tipo Descripción Largo/Formato l Cada tipo primitivo (excepto short y byte)
byte Entero de un byte 8 bits, C-2 tiene una clase declarada en el paquete
short Entero corto 16 bits, C-2 java.lang
int Entero 32 bits, C-2 l Constantes declaradas:
long Entro largo 64 bits, C-2
l MIN_VALUE y MAX_VALUE
float Punto flotante de 32 bits, IEEE 754
l NEGATIVE_INFINITY y POSITIVE_INFINITY
precisión simple
double Punto flotante de 64 bits, IEEE 754 l NaN (Not a Number)
precisión doble
char Caracter 16 bits, Unicode
boolean Booleano (true y false)

12
Constantes de Datos
Primitivos Constantes Literales
l 178 Entero l 178 Entero
l 178L Largo l 178L Largo l ´c´ carácter
l 045 octal l \n nueva línea
l 345.125 doble prec.
l 0X45df Hexadecimal l \u8f4d Unicode
l 234.12D doble prec.
l 234.12F simple prec. l true booleano
l 345.125 doble prec.
l 23.7e-4 doble prec. l 234.12D doble prec.
l ´c´ caracter l 234.12F simple prec.
l 23.7e-4 doble prec.
l true booleano

Orden de Resolución de
Declaración de Variables Nombres
l [modificador] tipo variable {, variable}* l Declaración local a un bloque (e.g. Loop)
l Modificador es opcional l Parámetro de un constructor o método
l Posibles modificadores: static o final
l Un miembro de una clase o interfaz
l static sólo se puede usar en campos (fields)
l Ejemplo: float[] x, y; l Tipos explícitamente importados
l Declaraciones pueden aparecer en cualquier parte l Otros tipos declarados en el mismo paquete
del código l Tipos importados implícitamente nombrados
l La visibilidad de una variable se limita al bloque en l Paquetes disponibles en el sistema host
que se declara

Valores Iniciales
l Una variable se puede inicializar en su declaración
l Ejemplo: Operadores
l final double π = 3.14159;
l Java asigna valores por omisión a los campos de
una clase si no se especifica
l Corresponde a valor 0 o null
l Variables locales de un método, constructor o
inicializador estático no se inicializan
l Una variable se inicializa cada vez que se ejecuta
su declaración

13
Precedencia y Asociatividad Precedencia de Operadores
de Operadores (1/2)
l A igual precedencia, se asocia por la izquierda,
excepto asignación que es por la derecha Unario posfijo [] . (param) ++ --

Menor precedencia
l La precedencia se pueda cambiar usando Unario prefijo ++ -- + ~ !
paréntesis Creación y cast new (tipo) exp
l Para legibilidad se recomienda usar paréntesis, Multiplicativo * / %
cuando sea posible, de manera de hacer explícita la Aditivo + -
precedencia, sin exagerar
Shift << >> >>>
l Ejemplo:
Relacional < > >= <= instanceof
while ((v = stream.next()) != null)
procesar(v); Igualdad == !=

Precedencia de Operadores
(2/2) Expresiones
l Una expresión se evalúa de izquierda a derecha
l AND al bit &
l Orden puede ser importante cuando existen efectos
Menor precedencia

l OR exclusivo al bit ^ laterales o corto-circuito


l OR inclusivo al bit | l En general, cada operando se evalúa antes de
l AND lógico && realizar la operación
l OR lógico || l Cada expresión tiene un tipo
l Condicional ?: l En general domina el operando de mayor rango de valores
l Asignación = += -= *= /= %= (e.g. double + long → double)
>>= <<= >>>= &=
^= |=

Conversión de Tipo: Implícita Conversión de Tipo: Explícita


l Conversión implícita. ¡Es automática! l Se requiere cuando un tipo no se puede asignar
l Valores Primitivos. Se permite entre valores primitivos a otro por conversión implícita
cuando se soporta un mayor rango de valores l La conversión explícita se denomina cast
l No se permite de punto flotante a entero l Ejemplo:
l En la conversión se puede perder precisión double d = 7.99; long l = (long) d;
l Referencias. Una referencia a un objeto de una clase l Se puede usar para referencias a objetos con
incluye una instancia de cada supertipo conversión no segura
l Se puede usar una referencia a un objeto de un tipo
cuando se requiera una referencia a un supertipo l Operador instanceof permite verificar se se
puede aplicar cast a un objeto
if (obj instanceof clase) ....
l null instanceof tipo es siempre falso

14
Operadores de Incremento y
Operadores Aritméticos Decremento
l Se soporta para todos los tipos de números l Operador de incremento
l Suma + l a++ equivale a a = a+1

l Resta - l Operador de decremento


l a-- equivale a a = a-1
l Multiplicación *
l Ambos operadores existen en forma prefija y
l División /
postfija
l Residuo o módulo % l Prefijo calcula primero la operación y luego se aplica;
l Además cambio de signo - postfijo es al revés
l Ejemplo: arreglo[i++]

Operadores Relacionales Operadores al Bit


l Mayor que > l AND al bit &
l OR inclusivo al bit |
l Mayor o igual que >=
l OR exclusivo al bit ^
l Menor que < l Corrimiento a la izquierda <<
l Menor o igual que <= (rellenando con 0)
l Corrrimiento a la derecha >>
l Igual que == (rellenando con el signo)
l Diferente != Corrimiento a la derecha >>>
(rellenando con 0)

Operador Condicional Operador de Asignación


l La forma l El operador = corresponde a la asignación,
valor = test ? exp1 : exp2; operador de menor precedencia
l Es equivalente a: l Java soporta otras formas de asignación
if (test) l += -= *= /= %= >>= <<= >>>= &=
valor = exp1; ^= |=
else valor = exp2; l Ejemplo:
l La diferencia es que el operador condicional define l arreglo[indice()] += 12 es casi equivalente a
valor y permite expresiones más compactas arreglo[indice()] = arreglo[indice()] + 12
l Segundo caso llama dos veces a indice()

15
Sentencias y Bloques
l Un bloque básicamente se compone de:
Control de Flujo l Sentencias de expresión
l Asignación
l Formas de prefijo o postfijo de ++ y --
l Llamadas a métodos ( objeto.metodo(...) )
l Creación de objetos (con new)
l Sentencias de declaración
l Variables requieren de inicialización
l Toda sentencia se termina con ;
l Un bloque se forma con { y }

Sentencia if-else Sentencia switch


l Forma básica de flujo de control l Evalúa una expresión entera cuyo valor se usa
condicional para seleccionar caso mediante etiqueta
if (exp-booleana) l Si no se encuentra etiqueta se salta a default
sent1 l Si no existe default, no se hace nada
else sent2 switch (valor) {
case 0: case 2: case 4: case 6: case 8:
l El else se parea con el if más cercano System.out.println (“es par”);
break;
case 1: case 3: case 5: case 7: case 9:
if (valor >= 0) Mal asociado System.out.println (“es impar”);
if ( valor < MAX) el else break;
process(valor); default: System.out.println (“es impar”);
else System.out.println (“valor negativo ”) }

Sentencia while y do-while Sentencia for


l Permite repetición controlada por expresión l Permite controlar una repetición para un
boolena rango de valores
l Las dos formas son: l La forma es la siguiente:
for (exp-inicial; exp-boolena; exp-incremento)
sentencia
while (exp-boolena ) do
sentencia sentencia l Esta forma equivale a:
while (exp-boolena );
exp-inicial;
while (exp-boolena ) {
sentencia
exp-incremento;
}

16
Sentencia break Sentencia continue
l Permite salir desde l La sentencia continue permite saltar al final
cualquier bloque, no buscar: del cuerpo de una repetición y evaluar la
sólo switch for(y=0; y<MAX; y++) {
for (x=0; x<MAX, x++) { condición de término
l Se usa para terminar if (Matriz[x][y] == valor) { l Se usa para ignorar una elemento de
una repetición como encontrado = true;
break buscar; proceso
for, while o do }
l Se puede usar una } while (! stream.eof ()) {
} elem = stream.next();
etiqueta para salir de if (elem == “ “ || elem == “ \n”)
if (! encontrado)
un anidamiento de System.out.println (“no está”); continue;
bloques procesar(elem);
}

Sentencia return
l Permite terminar la ejecución de un método y
retorna al invocador. 3.4 Clases y Objetos
l Si no retorno valor: return;
l Si retorna valor: return valor; Clases, miembros, constructores,
control de acceso

Conceptos Generales Estructura de una Clase


l Las clases contienen los métodos que definen la Nombre Variable
computación de la public class Persona { miembro
clase private int ID;
l Los campos (fields) o variables miembros definen private String Nombre;
el estado Cons-
l Las clases proveen la estructura para los objetos y public Persona (String s, int id) { tructor
el mecanismo para su creación Control Nombre = s; ID = id;
de }
l Un método tiene una firma, pero su implementación Acceso Firma del
define su semántica del public String miNombre(int id) { método
l Los métodos definen una suerte de contrato sobre miembro if (id == ID)
return Nombre; Implemen -
lo que hace un objeto de la clase
else return null; tación del
} método
}

17
Modificadores de la Clase Variables Miembros
l Las variables de clases se denominan tb. campos
l public
l Cada objeto de una clase tiene sus propias instancias de cada
l Por omisión una clase sólo es accesible por variable miembro
clases del mismo paquete, salvo que sea l Significa que cada objeto tiene su propio estado
declarada pública l Cambio de estado en un objeto no afecta a otros objetos
similares
l abstract l Variables miembros se pueden compartir entre todos los objetos
l La clase no puede ser instanciada de una clase con el modificador static
l Todos los objetos de una clase comparten una única copia de
l final un campo declarado como static
l La clase no puede ser derivada l En general, cuando se habla de variables y métodos miembros
se refiere a aquellos no estáticos

Ejemplo de Variable Miembro Control de Acceso de


Estática Miembros
class Persona { l Todos los métodos y variables miembro están
private static int nextID = 0; disponibles para el código de la propia clase
private int ID;
private String Nombre; l Para controlar el acceso a otras clases y subclases,
Variable los miembros tienen 4 posibles modificadores:
Estática public Persona (String s) { l Privado: Declarados con private son sólo accesibles por la
(o de ID = ++nextID; propia clase
Clase) Nombre = s; l Paquete: Miembros sin modificador de acceso son sólo
} accesibles por código y heredados por subclases en el mismo
paquete
public int getID() {
return ID; l Protegido: Declarados con protected son accesibles por una
} subclase, como también por código del mismo paquete
} l Público : Declarados con public son accesibles por cualquier
clase

Creación de Objetos Constructores


Persona p1; l Un objeto recién creado debe inicializar las
Persona p2 = new Persona(“Pedro”); variables miembro
l Se han declarados dos referencias a objetos de clase l Las variables miembro pueden ser inicializadas
Persona explícitamente en la declaración
l La declaración de una variable no crea un objeto, sino que l Muchas veces se requiere algo más
una referencia a un objeto, que inicialmente es null l Ejemplo: ejecutar código para abrir un archivo
l Cuando se usa el operador new, el runtime crea un objeto, l Los constructores cumplen ese propósito, tienen
asignando suficiente memoria, e inicializando el objeto con el mismo nombre de la clase y pueden recibir
algún constructor parámetros
l Si no existe suficiente memoria se ejecuta el recolector de
basura ( garbagge collector ), y si aun no existe suficiente l Los constructores no son un método (no retornan
memoria, se lanza la excepción OutOfMemoryError un valor)
l Terminada la inicialización, el runtime retorna la referencia al l Una clase puede tener varios constructores
nuevo objeto

18
Razones para usar
Ejemplo de Constructor Constructores
class Persona { l Algunas clases no tienen un estado inicial razonable
private static int nextID = 0; sin inicialización (e.g. tope = -1)
private int ID;
private String Nombre; l Proveer un estado inicial conveniente y razonable
Constructor (e.g. Nombre = “Juan”)
public Persona (String s) { l Construir un objeto puede ser costoso
ID = ++nextID;
Nombre = s; (e.g. objeto crea tabla interna a la medida)
} l Por motivos de seguridad de acceso
public int getID() { (e.g. constructores pueden ser privados o
return ID; protegidos)
}
} l Si no se define un constructor, el compilador agrega
uno por defecto.

Control de Acceso de Constructor por Omisión


Constructores (default)
l private l Si no se define constructor, se asume un
l Ninguna otra clase puede instanciar la clase (e.g. Clase constructor sin argumentos, que no hace
fábrica)
nada
l protected
l Sólo subclases de las clase y clases del mismo paquete l Este constructor por omisión se asume que
pueden crear instancias existe, si no se ha definido un constructor sin
l public argumentos
l Cualquier clase puede crear una instancia l El constructor por omisión es público si la
l Sin Especificador (acceso de paquete) clase lo es, sino no lo es
l Sólo clases del mismo paquete y de la misma clase
pueden crear instancias

Ejemplo de Múltiples
Métodos
Constructores
class Persona { l Un método se entiende para manipular el estado del
private static int nextID = 0;
private int ID; objeto (variables miembro)
private String Nombre; l Algunas clases tienen variables miembro públicas,
private int edad = -1;
lo que permite su manipulación directa por otros
public Persona (String s) { objetos, pero no es seguro
Segundo ID = ++nextID;
Nombre = s; l Cada método se llama con la siguiente sintaxis:
constructor
} referencia.metodo(args)
public Persona(String s, int ed) { l Java no permite un número variable de argumentos
this(s ); como C o C++
edad = ed;
} Invoca
Constructor
//... Otros métodos anterior
}

19
Métodos: Valores de Control de Acceso con
Parámetros Métodos
l En Java todos los parámetros se pasan por l Para proteger campos de un acceso externo se usa
el modificador private
valor (tanto primitivos como referencias)
l Java no provee un modificador que sólo permita
l Es decir, se pasa una copia del dato al método lectura de un campo
l Si el parámetro es una referencia, es la l Para asegurar acceso de sólo lectura se debe
referencia la que se copia, no el objeto introducir un nuevo método que lo haga
indirectamente y en forma segura
l Por lo tanto, un cambio de estado del objeto l Este tipo de métodos se denominan accesor
referenciado realizado por el método será visible
l Es recomendable usar accesores para proteger el
después del retorno estado de los objetos

Ejemplo: Método Accesor Referencia this


class Persona {
private static int nextID = 0; l Sólo se puede usar en un método no estático, y se
private int ID; refiere al objeto actual sobre el que se invocó el
private String Nombre; método
private int edad = -1;
l Implícitamente se usa this al comienzo de cada
public int getID() {
Método return ID; miembro propio referenciado por el código
accesor } l Ejemplo: En el ejemplo anterior
public int getID() {
public String getNombre() {
return Nombre; return ID;
} }

//... Otros métodos Se refiere a:


} this.ID

Usos de this Usos de this


public class Padre {
l Se usa usualmente para pasar una referencia del private String nombre;
objeto actual como parámetro a otro método private Hijo primogenito ;
l Ejemplo: Timer.wakeup(this, 30);
l Otro uso es cuando existe ocultamiento de una public Padre(String n){
identificador debido a colisión de nombres nombre=n ;
l Ejemplo }
public SetEdad (int edad) { public String getNombre(){
this.edad = edad; return nombre;
} }
l Similarmente a lo anterior, para tener acceso a public void nuevoHijo(Hijo h){
miembros ocultos de una superclase (por primogenito=h ;
redefinición: overriden), se puede usar super primogenito.asignarPadre(this) ;
}
}

20
Usos de this Usos de this
class Hijo{

private String nombre;


private int edad; public static void main(String [] args ) {
private Padre papa; Padre p = new Padre("Anakin");
Hijo h = new Hijo( "Luke", 10);
public Hijo(String n, int e){ System.out.println(h.nombrePadre());
nombre=n;edad=e; p.nuevoHijo(h);
} System.out.println(h.nombrePadre());
public void asignarPadre(Padre p ) { }
papa=p;
}

public String nombrePadre (){


if(papa== null )return "N.N .";
N.N.
else return papa.getNombre(); Anakin
}
}

Sobrecarga de Métodos Miembros Estáticos


l Cada método tiene una firma (signature): l Un miembro estático es único para toda una
l Nombre del método clase, en vez de tener uno por objeto
l Número y tipos de parámetros l Variable miembro estática. Existe una única
l El tipo de retorno variable para todos los objetos de una clase
l Java permite tener varios métodos con un mismo l Se deben inicializar antes de que se use cualquier
nombre, pero diferentes parámetros variable estática estática o método de la clase
l Se denomina sobrecarga (overload) l Método Estático. Se invoca en nombre de toda
l Cuando se invoca un método sobrecargado, se la clase
calza con los parámetros usados l Sólo puede acceder a miembros estáticos (e.g. no
permite usar this)
l Se invocan típicamente usando nombre de la clase
l Se denominan también métodos de clase

Bloques de Inicialización
Ejemplo: Método Estático Estática
estático l Permiten a una clase inicializar variables
public class PruebaUsoStack {
int x=0; miembro estáticas u otros estados necesarios
public static void main(String[] args) { l Se ejecutan dentro de una clase en el orden que
Stack st = new Stack(5);
aparecen declarados
st.push ("Hola"); l Ejemplo:
Clase st.push(args[0]);
class Primos {
System String s; protected staticint[] PrimosConocidos = new int[4];
miembro while (st.size()>0) {
estático out s = st.pop(); static {
System.out.println(s); PrimosConocidos[0] = 2;
} for (int i = 1; 1 < PrimosConocidos.length; i++)
System.out.println(x ); PrimosConocidos[i] = ProximoPrimo();
} }
ERROR
} }

21
Recolección de Basura Método finalize
l Java realiza recolección automática de basura, i.e. l Permite ejecutar un método de finalización antes de
el programador no requiere liberar explícitamente liberar memoria
los objetos l Es el equivalente al concepto de destructor en C++
l Sólo existe new (no delete como C++)
l Es útil cuando se usan recursos no de Java y que
l Objeto que se detecta sin referencia, el sistema lo libera deben liberarse (evitar fuga de recursos)
l Ventajas l Ejemplo: Cerrar archivos abiertos
l No requiere invocar al administrador de memoria para l Forma de declararlo:
liberar cada objeto
l No se produce el problema de dangling protected void finalize() throws Throwable {
super.finalize();
// ...
}

Ejemplo de finalize Método main


public class ProcesarArchivo {
private Stream Archivo; l El método main se debe encontrar en cada
publicProcesarArchivo (String nombre) { aplicación Java
Archivo = new Stream(nombre);
} l El método debe ser público, estático y void
// ...
publicvoid close() { l EL argumento único es un arreglo de String,
if (Archivo != null) {
Archivo.close();
que se consideran los argumentos del
Archivo = null; programa
}

protected void finalize() throws Throwable {


super.finalize();
close();
}
}

Ejemplo Método toString


El archivo fuente Echo.java l Si un objeto soporta el método public String toString(),
este método se invoca en cualquier expresión en que el
class Echo {
objeto aparezca con los operadores + y +=
public staticvoid main (String[] args) {
for (int i = 0; i < args.length; i++) l Ejemplo: class Persona {
System.out.print(args[i] + “ “); private int ID;
System.out.println(); private String Nombre;
}
public String toString() {
return ID + “ : “ + Nombre;
La ejecución del programa: }
//... Otros métodos
>java Echo que argumentos recibe
}
que argumentos recibe Ejemplo de uso
> Persona p; //...
System.out.println (“La persona” + p);

22
Métodos Nativos Clases Anidadas
l Permite que programas Java usen código no l Java permite definir una clase como miembro
escrito en Java de otra clase
l Se implementa el método en lenguaje nativo (e.g. l Útil cuando una clase tiene sólo sentido en el
C ó C++) contexto específico de una clase
l El método se invoca desde Java l Clase anidada tiene acceso total a todas los
l Se pierde la portabilidad y seguridad de Java miembros de la clase a que pertenece (como
lo haría cualquier otro método miembro de la
l Se aplica para manipular hardware clase superior)

Clases Internas Ejemplo de Clase Interna


l Si clase anidada se declara estática, se llama clase public class Stack { class StackEnum implements Enumeration {
private Vector items; int itemActual = items.size() - 1;
anidada estática
l No tiene acceso a miembros no estático // código de métodos y constructores de Stack publicboolean hasMoreElements() {
return (ItemActual >= 0);
l Permite sólo relacionar clases (no instancias) public Enumeration enumerator() { }
l Si no es estática, es una clase interna return new StackEnum();
} publicObject nextElement () {
l No puede definir miembros estáticos if (!hasMoreElements())
l Permite crear objetos de la clase interna dentro de la clase // aquí viene declaración de clase interna thrownew NoSuchElementException();
a que pertenece // ... else
return items.elementAt(ItemActual--);
l Permite relacionar objetos de las clases relacionadas }
l Puede ser pública o privada }

} // fin de declaración de Stack

Resumen
l Objeto y Clase
l Miembros (métodos y variables) 3.5 Herencia
l Creación de objetos y constructores
l Control de acceso Extensión de clases, redefinición
l Sobrecarga de métodos y constructores de miembros, constructores,
l Miembros estáticos clases y métodos abstractos,
l Métodos especiales (finalize, main, toString) clase Object
l Clases anidadas

23
Conceptos Preliminares Clases Extendidas
l En general, una clase define un contrato de uso a l En Java todas las clases son extendidas
través de sus miembros accesibles y el l Toda clase se deriva (quizás indirectamente) de la clase
Object
comportamiento esperado de los métodos
l La clase Object implementa el comportamiento que
l Una clase extendida agrega funcionalidad, requiere todo objeto Java
creándose una nueva clase, con un contrato l Java sólo permite tener una única superclase
extendido (herencia simple )
l No se cambia el contrato que se hereda de la l Si no se especifica extends se supone que se deriva de
superclase, sino que se extiende
Object
l Si se puede cambiar la implementación de algunos
métodos heredados, pero respetando el contrato de la
superclase

Ejemplo: Clase Extendida Reglas de Herencia


public class StackPrint extends Stack { l Una subclase hereda todos los miembros
l protegidos
public StackPrint(int i) { l Públicos
Superclase
super(i); l Sin modificador (paquete) mientras la subclase se declare
} en el mismo paquete
Constructor l Colisiones de nombres
public void print() {
System.out.println("tamaño: " + (top+1)); de la l En el caso de una variable miembro, ésta se oculta
for (int i=0; i<top+1; i++) { Superclase l En el caso de un método, éste es redefinido (overriden)
System.out.println(i + ": " + buffer[i]);
}
}

Redefinición de Variables Ejemplo de Ocultamiento:


Miembros Variables Miembros
l Los campos no se pueden realmente
redefinir, sólo pueden ser ocultados class SuperClase {
l Si se declara un campo con el mismo Number numero;
}
nombre de uno de la superclase, este último
sigue existiendo, pero no es accesible class SubClase extends SuperClase {
directamente desde la subclase Float numero;
l Para accederlos se puede usar referencia }
super
Acceso a SuperClase en SubClase: super.numero

24
Redefinición (overriden) de Métodos Redefinición (overriden) de Métodos
(1/3) (1/3)
public class Traductor {
l Para la definición de métodos donde existe public String traducir(String palabra){
...
coincidencia de nombres: }
}

l Sobrecarga: Definir más de un método con el mismo class MultiTraductor extends Traductor{
nombre, pero con diferente firma public String traducir(String palabra, String idioma){
...
l Redefinición . Reemplaza la implementación de la }
}
superclase
class TraductorMandarin extends Traductor{
l Firma y tipo del retorno deben ser idénticas public String traducir(String palabra){
...
l Permite modificar o complementar el comportamiento }
de un método de la superclase }

l Se puede invocar el método redefinido desde la class TraductorMapudungun extends Traductor{


public String traducir(String palabra){
superclase con la referencia super ...
}
}

Redefinición (overriden) de Métodos Ejemplo de Redefinición de


(3/3)
Miembros (1/2)
l Un método redefinido sólo puede dar más acceso,
no menos public class SuperClase { public class SubClase extends SuperClase {
l Ejemplo: un método público de la superclase no se puede public String str = "SuperClase.str"; public String str = "SubClase.str ";

declarar privado en la subclase void mostrar() { void mostrar() {


System.out.println( System.out.println(
l Métodos que no se pueden redefinir: "SuperClase.mostrar = " + str); "SubClase.mostrar = " + str);
} }
l Métodos finales }
public static void main(String[] args) {
l Métodos estáticos (de la clase): si lo puede ocultar SubClase sub = new SubClase();
SuperClase sup = sub;
declarando un método con la misma firma Resultado de Ejecución sup.mostrar();
sub.mostrar();
l Métodos que se deben redefinir: SubClase.mostrar = SubClase.str System.out.println("sup.str = " + sup.str);
System.out.println("sub.str = " + sub.str);
SubClase.mostrar = SubClase.str
l Métodos que han sido declarados abstractos en la sup.str = SuperClase.str
}
}
sub.str = SubClase.str
superclase

Constructores en Clases
Ejemplo de Redefinición de
Extendidas
Miembros (2/2)
public class SuperClase { public class SubClase extends SuperClase { l Al crear un objeto, el orden de ejecución es:
public String str = "SuperClase.str"; public String str = "SubClase.str ";
l Se invoca el constructor de la superclase
void mostrar() { void mostrar() {
System.out.println( super.mostrar(); (sino se especifica cual, se usa el por omisión)
"SuperClase.mostrar = " + str); System.out.println(
} "SubClase.mostrar = " + str); l Inicializar los campos usando sentencias de inicialización
} }
public static void main(String[] args) { l Ejecutar el cuerpo del constructor
SubClase sub = new SubClase();
SuperClase sup = sub;
sup.mostrar(); l Si se quiere usar un constructor específico de la
Resultado de Ejecución sub.mostrar();
SuperClase.mostrar = SuperClase.str System.out.println("sup.str = " + sup.str); superclase debe invocarse con super(...)
SubClase.mostrar = SubClase.str System.out.println("sub.str = " + sub.str);
SuperClase.mostrar = SuperClase.str }
}
SubClase.mostrar = SubClase.str
sup.str = SuperClase.str
sub.str = SubClase.str

25
Ejemplo de Constructor (1/2) Ejemplo de Constructor (2/2)
public class subclase extends superclase {
private int Z = 3 ;
public class superclase { public subclase() {
protected int X = 1; System.out.println("subclase antes: Y = " + Y);
protected int Y ; Y = Z;
System.out.println("subclase despues : Y = " + Y);
}
public superclase() { }
System.out.println("superclase: antes Y = " + Y);
Y = X; public class principal {
public static void main(String[] args) {
System.out.println("superclase: después Y = " + Y); System.out.println("Inicio de principal");
} subclase z = new subclase();
System.out.println("Fin de principal");
}
public int getY () {
}
Resultado de Ejecución:
return Y;
Inicio de principal
} superclase: antes Y = 0
} superclase: despues Y = 1
subclase antes: Y = 1
subclase despues: Y = 3
Fin de principal

Modificador final La Clase Object


l Se puede usar en tres situaciones diferentes: l Todas las clases tienen a Object como raíz,
l Variable . La variable no puede ser modificada por lo tanto heredan sus métodos
(constante) l Existen dos tipos de métodos:
l Método. El método no puede ser redefinido l Métodos de utilidad general
l Clase. La clase no se puede derivar l Métodos para soportar hebras (threads)
(implícitamente todos sus métodos son finales)
l El último tipo no lo estudiaremos en el
l Uso de final en métodos y clases restringe contexto de este curso
reuso, por lo que debe usarse con reserva

Object: Métodos de Utilidad Object: Métodos de Utilidad


General (1/2) General (2/2)
l public boolean equals(Object obj) l protected Object clone() throws
l Compara si dos objetos tienen el mismo valor CloneNotSupportedException
l Por omisión se supone que un objeto es sólo igual a si l Retorna un clon del objeto (una copia de un nivel)
mismo l public final Class getClass ()
l No es igual a verificar que tienen la misma referencia (se l Retorna un objeto de tipo Class que representa la clase
puede hacer con ==) del objeto this. Permite utilizar reflexión.
l public int hashCode() l public void finalize() throws Throwable
l Finaliza un objeto durante la recolección de basura
l Retorna código hash del objeto, que es usualmente único
para cada objeto l public String toString()
l Sirve para ser usados en tablas de hash l Retorna una representación del objeto en un String
l Mayor parte de las clases lo redefinen
l Utilizado por el operador ‘+’ entre strings y objetos

26
Métodos equals y hashCode Métodos equals y hashCode
public class Persona {
l Los métodos equals y hashCode deben ser private String rol;
private String nombre;

redefinidos conjuntamente private String telefono;


...
public String getRol (){
l Normalmente dos objetos diferentes retornan }
return rol;

diferentes códigos de hash public String toString(){


return rol+": "+nombre;
}
l Para que dos objetos diferentes sean iguales en public boolean equals(Object o){
if(!(o instanceof Persona))
valor deben retornar el mismo código de hash return false;
else{
Persona op = (Persona) o;
return this.getRol().equals(op.getRol ());
}
}
public int hashCode(){
return this.rol.hashCode();
}
}

Ejemplo de Igualdad de
Valores Clonación de Objetos
l El método clone permite clonar un objeto
public class Igualdad {
l En principio, cambios posteriores en el clon no afectan al
public static void main(String[] args ) { estado del objeto original
Integer Un = new Integer(1), otroUn = new Integer(1);
l Una clase que permite clonar objetos normalmente
if (Un.equals(otroUn)) implementa la interfaz Cloneable
System.out.println("objetos son iguales");
if(Un == otroUn) l Aquellas clases que tienen variables miembros que
System.out.println("objetos son idénticos"); son referencias deben redefinir el método clone
}
l Agrega profundidad
}

Ejemplo de Clonación Clases y Métodos Abstractos


public class Stack implements Cloneable { l Permite definir clases que definen sólo parte de su
private Vector items; implementación
// código de los métodos y constructor de Stack l Clases derivadas deben implementarlas
protected Object clone() { l Abstracción es útil cuando:
try {
Stack s = (Stack) super.clone (); // clona el stack l algún comportamiento es verdad para la mayoría de los
s.items = (Vector) items.clone(); // clona el vector
return s; // return the clone
objetos de un tipo dado,
} catch ( CloneNotSupportedException e) { l pero algún comportamiento sólo tiene sentido para
// esto no debiera suceder dado que el Stack es clonable
throw n e w InternalError();
algunos, no para toda la superclase
}
}
l Una clase abstracta no requiere declarar métodos
} abstractos, pero una clase que tiene un método
abstracto debe ser declarada como clase abstracta

27
Cuándo y cómo extender
Ejemplo de Clase Abstracta Clases?
abstract class ObjectoGrafico { class Circulo extends ObjectoGrafico {
int x, y; void dibujar() { l Una clase que se extiende sigue siendo del tipo
. . .
void mover(int nuevoX , i n t nuevoY) { }
. . .
de la superclase (isA), no viceversa
. . . } l Ejemplo: Se se deriva pixel de punto, un pixel es un
}
class Rectangulo extends ObjectoGrafico { punto, pero un punto no es un pixel
abstract void dibujar(); void dibujar() {
} . . . l A veces se extiende agregando nuevos
}
}
miembros (hasA)
l Ejemplo: Un círculo tiene un punto, pero no es un
círculo.
...
ObjetoGrafico [] arreglo; l En casos que la extensión permite tener
... diferentes roles es más conveniente usar
for(int i=0;i<arreglo.length;i++) agregación
arreglo[i].dibujar();
... l Ejemplo: Una persona que tiene roles diferentes no es
simple extenderla por derivación

Resumen
3.6 Interfaces y
l Definición de Interfaz
l Herencia Múltiple
Paquetes
l Supertipos y Subtipos
Interfaces, implementaciones,
paquetes, organización de
archivos

Introducción
l Mecanismo de Interfaz es una manera de declarar
3.6.1 Interfaces tipos consistentes sólo de métodos abstractos y
constantes
Declaración, Herencia múltiple, l Clases deben implementar los métodos de las
interfaces
supertipos y subtipos,
l Las interfaces son útiles para el diseño
implementación l Clases deciden cómo implementar
l Una interfaz puede tener muchas implementaciones

28
Interfaz vs. Clase Abstracta Ejemplo de Interfaz (1/2)
l Interfaz es una simple lista de métodos abstractos l Clase que puede monitorear variación de precios de las acciones
(no implementados) l ObservadorAcciones es una interfaz de un observador
l Método cambioValor permite ser notificado de cambio precio
l Una interfaz se diferencia de una clase abstracta
l Un objeto de una clase que implementa esta interfaz se registra con
en: método observarAcciones para ser notificado de cambios
l Una interfaz no puede implementar ningún método, una l accionMon permite definir la acción que interesa observar y delta la
clase abstracta si lo puede variación que ese considera interesante
l Una clase puede implementar varias interfaces, pero
puede tener una única superclase public class MonitorAcciones {
public void observarAcciones (ObservadorAcciones observador,
l Una interfaz no puede ser parte de una jerarquía de clases String accionMon, double delta) {
...
l Clases no relacionadas pueden implementar una misma }
interfaz }

Ejemplo de Interfaz (2/2) Declaración de Interfaz


Declaración de la interfaz
public interfaz < nombre interfaz> extends
<lista de super-interfaces> {
<cuerpo de la interfaz>
public interface ObservadorAcciones { Constantes
}
final String enersisMon = ”Enersis";
final String santaIsabelMon= ”Santa Isabel";
final String copecMon = ”Copec";

void cambioValor(String accionMon , double nuevoValor); l public hace pública la interfaz fuera del paquete
} Método
(opcional)
l La interfaz puede extender varias interfaces
Cuerpo de la Interfaz (opcional)

Implementación de una
Cuerpo de la interfaz Interfaz
l Todas las constantes son implícitamente: l Una interfaz define un conjunto de métodos.
l públicas,
l estáticas y l Una referencia a una interfaz permite
l finales suponer que los métodos existen
l Todos los métodos son implícitamente: l Una clase que “implementa” una interfaz se
l públicos y
compromete a “implementarlos”.
l abstractos
l No se aceptan otros modificadores (e.g. private, l Definir código para cada uno de ellos.
protected y synchronized) l Incumplimiento de contrato implica imposibilidad
de crear instanciasàclase abstracta
l Se deja la responsabilidad a los hijos.

29
Implementación de una Implementación de una
Interfaz Interfaz
public interface ObservadorEventos { public class Agenda {

public void nuevoEvento(Date fecha, String evento);


private Vector observadores=new Vector();
} ...
public void agregarObservador(ObservadorEventos o){
observadores.add(o);
public class Asistente implements ObservadorEventos {
}
public void nuevoEvento(Date fecha, String evento){
System.out.println("Avisarle al jefe antes de las "+fecha+"!!");
public void nuevoEvento(String evento){
}
for(int i=0;i<observadores.size();i++){
}
ObservadorEventos oe = (ObservadorEventos) observadores.get(i);
oe.nuevoEvento(new Date(), evento);
public class Persona implements ObservadorEventos{
}
...
public void nuevoEvento(Date fecha, String evento){ }
System.out.println("Ir a tomar la micro para la '"+evento+"'!"); }
}
}

Implementación de una
Interfaz Herencia Simple vs. Múltiple
l Una clase puede extender exactamente una
public static void main(String args[]){ superclase
Agenda a = n e w Agenda();
l Una interfaz puede extender múltiples interfaces
Persona p = new Persona("NN", "112233");

Asistente asist = new Asistente(); l Herencia múltiple con clases puede producir
a.agregarObservador(p ); problemas debido a diferentes implementaciones
a.agregarObservador(asist );
l Ejemplo: W
a.nuevoEvento ("reunion");
l W tiene un campo wVar
} Y X
l Si Z hace referencia a wVar,
cuál es? Existen dos wVar?
Z
Ir a tomar la micro para la ‘reunion’!
Avisarle al jefe antes de las Mon Apr 05 17:08:49 VET 2004!! l Java evita el problema permitiendo sólo herencia
simple para clases

Ejemplo de Interfaz Extendida


Extensión de interfaces (1/3)
l Al igual que las clases, las interfaces pueden public interface AdministradorRecursos {

tener súper-interfaces. public void agregarRecurso(String nombre, String driver);


public Collection recursosRegistrados ();
l La interfaz hija “hereda” las definiciones de la }

interfaz padre. public interface AdministradorEntrada extends AdministradorRecursos{


l En este caso se permite herencia múltiple public Collection recursosDirectos ();

public Collection recursosConBuffer();


}

public interface AdministradorSalida extends AdministradorRecursos {


public boolean bloquearRecurso(String recurso);

30
Ejemplo de Interfaz Extendida Ejemplo de Interfaz Extendida
(2/3) (3/3)
public class ControladorHDDs implements AdministradorES {

public void establecerBloqueos(i n t tipo) {...}


public Collection recursosDirectos() {...}

public interface AdministradorES public Collection recursosConBuffer( ) {...}

public boolean bloquearRecurso(String recurso) {...}


extends AdministradorEntrada, AdministradorSalida {
public void agregarRecurso(String nombre, String driver) {...}

public Collection recursosRegistrados() {...}

public void establecerBloqueos(int tipo); }

} public class PanelRemoto implements AdministradorES {

public void establecerBloqueos(i n t tipo) {...}

public Collection recursosDirectos() {...}

public Collection recursosConBuffer( ) {...}

public boolean bloquearRecurso(String recurso) {...}


public void agregarRecurso(String nombre, String driver){...}

public Collection recursosRegistrados() {...}

Conflictos de Nombres Modificación de Interfaces


l ¿Qué pasa si un mismo nombre se encuentra en l Una interfaz una vez declarada no debiera ser
más de una interfaz de los supertipos? modificada
l Si las firmas no son idénticas, es trivial (se sobrecargarán l Ejemplo: Si se modifica la interfaz ObservadorAcciones
diferentes métodos) agregando un nuevo método, todas las clases que la
l Si tienen firma idéntica, entonces la clase tendrá un solo implementan no son más válidas
método con esa firma
l Por lo tanto, definición de una interfaz requiere diseño
l Si las firmas sólo difieren en el tipo de retorno, no se
puede implementar la interfaz cuidadoso

l Para constantes es simple: se selecciona cada una l Problema anterior se soluciona definiendo una
usando nombre de la interfaz subinterfaz con el nuevo método
l Ejemplo: X.var, Y.var

Interfaces comunes a Ejemplo de Implementación de


implementar Interfaz (1/2)
public class Proceso implements Comparable {
l java.util.Iterator private static i n t lastPid=1;
l hasNext(), next(), remove() private int pid;

l java.util.Collection private int priority;

l add(), addAll(Collection c), clear(), contains (), ... public Proceso(){

l java.lang.Comparable pid=++lastPid ;

priority=0;
l compareTo(Object o)
}
l java.lang.Cloneable public i n t getPid (){return p i d;}
l Vacia! public void nice( int p){priority+=p; }

l java.lang.Runnable public i n t compareTo(Object o ) {

l run() if(!(o instanceof Proceso))

l java.awt.event.ActionListener throw new ClassCastException();

l actionPerformed(ActionEvent e) return this.pid - ((Proceso) o).getPid( ) ;

}
}

31
Ejemplo de Implementación de
Interfaz (2/2)
class DemoIterador implements java.util.Iterator {
private String[] Cartas = {
"2","3","4","5","6","7","8","9","10" ,"Sota", "Reina", "Rey","As" } ;
private int actual = 0;

public boolean hasNext() {


3.6.2 Packages
if (actual == Cartas.length) {
return false;
else
return true;
}
public Object next() {
return (Object) Cartas[actual++];
}
public void remove() {
throw new UnsupportedOperationException();
}
public static void main(String[] args) {
DemoIterador i = new DemoIterador ();
while (i.hasNext()) {
System.out.println(i.next ());
}
}
}

Concepto de Paquete Mecanismo de Definición


l Contiene clases, interfaces y subpaquetes l En la primera línea de cada archivo fuente de una
que están relacionados clase o interfaz debe aparecer:
package <nombre>
l Razones para definirlos:
l El nombre del paquete implícitamente se antepone
l Permiten agrupar interfaces y clases relacionadas al nombre de la clase o interfaz
l Interfaces y clases pueden usar nombres públicos Ejemplo: miPaquete.miClase
populares sin tener conflictos con otros paquetes l Código externo al paquete puede referenciar a tipo
l Paquetes pueden tener componentes que sólo internos del paquete de acuerdo a las reglas de
están disponibles dentro del paquete control de acceso
l Facilita la distribución de software

Ejemplo de uso de Paquete Referencias Externas


package personas
l Una forma es anteponer el nombre del paquete a
cada tipo (si existen subpaquetes se puede definir
class Persona { una jerarquía)
private static int nextID = 0;
private int ID; l Esta forma es razonable si se usan pocas referencias a
private String Nombre; tipos del paquete
private int edad = - 1;
l La otra forma es mediante import , lo que permite
usar referencias en el código sin anteponer nombre
//... Otros métodos
} del paquete
l Ejemplo
import Personas.*
// ahora se puede usar la clase Personas sin
Se puede referenciar la clase Persona por:personas.Persona // anteponer nombre del paquete

32
Colisiones de Nombre entre Colisiones de Nombres de
Paquetes Paquetes
l Si se usa más de un paquete se pueden producir colisiones de l Si dos paquetes tienen el mismo nombre y
nombre.
l Para controlar el uso correcto se puede usar: requieren ser usados existe un problema
l 1. Anteponer el nombre del paquete en aquellos casos de l Una solución es usar nombres anidados
colisión (e.g. Personas.Persona)
l 2. Importar en forma completa un solo paquete y usar nombres l Ejemplo: miproyecto.mipaquete.*
completos para los nombres que colisionan
l Caso real l En grandes organizaciones se acostumbra a
l java.util.Date y java.sql.Date usar nombres de dominio de Internet en
orden inverso
l Ejemplo:
import Personas.* l Ejemplo: cl.utfsm.siga.mipaquete.*
// OtrasPersonas.Persona se refiere al otro paquete
// Persona se refiere ahora a Personas.Persona

Control de Acceso a Paquetes Recomendaciones


l Clases e Interfaces tienen dos accesos: l Paquetes se deben definir para clases e interfaces
l Público. Si se califican con public esta permitido su relacionadas
acceso fuera del paquete l Tal agrupación permite una mejor reutilización
l Paquete. Sino se declara public, su acceso se restringe l Permite usar nombres adecuados sin provocar colisiones
dentro del paquete l Los paquetes se pueden anidar
l Miembros de clase declarados: l Permite agrupar paquetes relacionados (e.g. java.lang)
l Sin modificador de acceso son accesibles dentro del l Es un asunto organizacional, no de control de acceso
paquete, pero fuera de él l Jerarquía típicamente se refleja en la estructura del
directorio
l Miembros no privados son accesibles por cualquier código
del paquete (son amistosos)

Paquetes y directorios Paquetes y directorios


l Los nombres de paquetes condicionan el package usm.lp.agenda;
lugar donde buscar las clases public class Agenda {
...
l La jerarquía de paquetes debe ser idéntica a
}
la jerarquía de directorios

~home/
usm/
lp/
agenda/
Agenda.java
Persona.java
....

33
Paquetes de Java Extensiones a Java
l java.lang l javax.swing
• java.rmi l javax.servlet
l java.io
• java.applet l javax.crypto
l java.util l javax.accessibility
• java.sql
l java.math l javax.naming
• java.beans javax.transaction
l java.awt l
• java.security l javax.xml
l java.net
• etc. l javax.sound
l javax.print
l etc.

Resumen
3.7 Caracteres, String
y Otros Tipos de
l Definición de Interfaz
l Herencia Múltiple
Datos
l Conflictos de Nombres
Arreglos, Character, String,
l Supertipos y Subtipos StringBuffer, Number, Date
l Implementación de Interfaces
l Paquetes
l Control de Componentes de Programas

Arreglos en Java
l Arreglos en Java son agrupaciones ordenadas de
3.7.1 Arreglos elementos
l Los elementos pueden ser tipos primitivos o
referencias (incluso referencias a otros arreglos)
l Las dimensiones de un arreglo se omiten en la
declaración de variables
l La dimensión se determina en la creación del arreglo
l Tamaño permanece fijo después de su creación
l Los índice varían desde 0 a largo-1
l Acceso ilegal lanza IndexOutOfBoundsException
l Los arreglos no se pueden derivar

34
Ejemplo de un Arreglo Uso de Arreglos
l Declaración de un Arreglo (sin tamaño)
public class demoArreglo {
l tipo[] variable;
public static void main(String[] args) { l Creación de un arreglo vacío (especifica tamaño)
// declarar un arreglo de enteros
int[] unArreglo; l variable = new tipo[tamaño];
// crear un arreglo de enteros
unArreglo = new int[10]; l Creación e inicialización rápida
// asigna un valor a cada elemento del arreglo e imprime
for ( int i = 0; i < unArreglo.length ; i + +) { l tipo[] variable = {val0 , val1 , ... , valn-1 };
anArray[i ] = i;
System.out.print(unArreglo[i] + " ") ; l Acceso a un elemento del arreglo
}
System.out.println();
l variable[indice]
}
}
l Tamaño del arreglo
l variable.length

Arreglo de Arreglos Copiado de Arreglos


public class ArregloDeArreglo {
l Para copiar un arreglo se puede usar método
public static void main(String[] args) {
String[][] cartoons = {
{"Flintstones ","Fred" ,"Wilma" ,"Pebbles", "Dino" } ,
arraycopy de System :
{"Rubbles ","Barney"," Betty"," Bam Bam " },
{"Jetsons ","George","Jane","Elroy "," Judy ","Rosie ","Astro" },
l public static void arraycopy(
{"Scooby Doo Gang ","Scooby D o o"," Shaggy" ,"Velma" ,"Fred", "Daphne" }
};
Object fuente,
for ( int i = 0; i < cartoons.length; i++ ) {
System.out.print(cartoons[i][0] + ": ");
int indiceFuente,
for ( int j = 1; j < cartoons[i].length; j++) Object destino,
System.out.print(cartoons[i][j] + " ");
System.out.println(); int indiceDestino,
}
} int largo)
}

Flintstones: Fred Wilma Pebbles Dino


Rubbles: Barney Betty Bam Bam
Jetsons: George Jane Elroy Judy R o s i e Astro
Scooby D o o Gang: Scooby Doo Shaggy Velma Fred Daphne

Ejemplo de Copia de Arreglos Utilidades para arreglos


public class DemoCopiaArreglos { l Clase utilitaria java.util.Arrays
public static void main(String[] args) { l static int binarySearch(<tipo>[] a, <tipo> key)
char[] copiarDesde = { 'd', 'e', 'c', 'a', 'f', 'e', 'i', 'n', 'a', 't', 'e', 'd' };
l static boolean equals(<tipo>[] a, <tipo>[] a2)
char[] copiarA = new char[7];
l static void fill(<tipo>[] a, <tipo> val)
l static void sort(Object[] a)
System.arraycopy(copiarDesde, 2, copiarA, 0, 7);
l Los objetos deben implementar la interfaz java.util.Comparable
System.out.println(new String(copiarA));
}
}
cafeina

35
Clases Básicas para
Caracteres
3.7.2 Caracteres y
l Character.Clases cuyas instancias pueden
Strings mantener un único valor (wrapper)
l String. Clase para almacenar y manipular
datos inmutables compuestos de múltiples
caracteres
l StringBuffer. Clase para almacenar y
manipular datos mutables compuestos de
múltiples caracteres

Métodos de Character Ejemplo de Character


l Character(char ) public class CharacterDemo {
l Constructor crea objeto inmutable public staticvoid main(String args[]) {
Character a = new Character('a');
l int compareTo(Character ) Character a2 = new Character('a');
l Retorna entero que compara con otro carácter Character b = new Character('b');
l boolean equals(Object) int diferencia = a.compareTo(b);
l Retorna true si son de igual valor if (difference == 0) {
System.out.println("a es igual a b.");
l String toString () } else if (diferencia < 0) {
l Convierte a string System.out.println("a es menor que b.");
l char charValue() } else if (diferencia > 0) {
l Retorna valor del objeto
System.out.println("a es mayor que b.");
}
l isUpperCase(char ) System.out.println("a es " + (( a.equals(a2)) ? “igual" : “no igual") + " a a2.");
l Retorna true si es mayúscula System.out.println(“El carácter " + a.toString() + " es " +
(Character.isUpperCase(a.charValue()) ? “mayúscula" : “minúscula"));
}
}

Ejemplo de String y Creación de Strings y


StringBuffer StringBuffers

l Java permite crear un String en diversas situaciones


public class StringsDemo {
public static void main(String [] args) { l Ejemplo:
String palindrome = “ recocer ";
“Este es un String" // literal
int largo = palindrome.length();
StringBuffer destino = new StringBuffer(len); String palindrome = “recocer"; // referencia String
for (int i = (largo - 1); i >= 0; i --) {
destino.append(palindrome.charAt(i)); char[] ArregloHola = { 'h', ‘o', 'l', ‘a'}; // arreglo de caracteres
}
System.out.println(destino.toString ()); String StringHola = new String(ArregloHola);
}
System.out.println(StringHola);
}

n StringBuffer debe siempre usar new para crear un


string

36
Métodos Accesores Métodos Específicos de
(Comunes) String
l int length() l indexOf(int caracter ),
lastIndexOf(int caracter )
l Obtiene el largo del String o StringBuffer
l Retorna índice de la primera (última) ocurrencia de caracter
l char charAt(int pos) l indexOf(int car , int desde) ,
l Obtiene carácter en posición pos. 0 es el primero y lastIndexOf(int car, int desde)
length()-1 el último l Retorna índice de primera (última) ocurrencia de carácter,
buscando hacia delante (atrás) desde índice especificado
l String substring(int), String substring(int, int) l indexOf(String str),
lastIndexOf(String str )
l Obtiene parte del String
l Retorna índice de la primera (última) ocurrencia del String str.
l Los dos enteros indican primera y última posición. Sino se l indexOf(String str, int desde ),
indica segundo entero, se asume hasta el final lastIndexOf(String str , int from)
l String toString() l Retorna índice de primera (última) ocurrencia de String str ,
buscando hacia delante (atrás) desde índice especificado.
l Convierte a string

Métodos Específicos de
String Métodos de StringBuffer
l int compareTo(String otroString)
l StringBuffer append(String str)
l Compara dos lexicográficamente(interfaz Comparable)
l Agrega str al final del buffer de string.
l String concat(String str)
l int capacity()
l Concatena el string str al final
l Retorna la capacidad actual del buffer de string
l String toLowerCase() l StringBuffer insert(int offset, String str)
l Convierte un String a minúsculas
l Inserta str en la posición offset del buffer de string.
l String toUpperCase() l StringBuffer delete (int inicio, int fin)
l Convierte un String a mayúsculas l Elimina los caracteres entre inicio y fin
l etc. l etc.
l VER: l VER:
http://java.sun.com /j2se/1.4/docs/api/java/lang /String.html http://java.sun.com /j2se/1.4/docs/api/java/lang /StringBuffer.ht
ml

Clase Number
l byte byteValue()

3.7.3 Números l
l Retorna el valor del número
double doubleValue()
especificado como byte

l Retorna el valor del número especificado como double


l float floatValue()
Wrappers y funciones l Retorna el valor del número especificado como float
l int intValue()
l Retorna el valor del número especificado como int
l long longValue()
l Retorna el valor del número especificado como long
l short shortValue()
l Retorna el valor del número especificado como short

37
Clases Extendidas de
Number Funciones Matemáticas
l Byte. Clase envolvente para byte l El paquete java.lang.Math contiene funciones tales
l Double. Clase envolvente para double como:
l Float. Clase envolvente para float l exponenciación
l logaritmos
l Integer. Clase envolvente para int l raíz cuadrada
l Long. Clase envolvente para long l Funciones trigonométricas
l Short. Clase envolvente para short l Máximos y mínimos
l BigDecimal. Número decimal de precisión arbitraria l Redondeos
l BigInteger. Número entero de precisión arbitraria l etc.
l Ver
l http://java.sun.com /j2se/1.4/docs/api/java/lang /Math.html

Formatos de Números
l Los programas almacenan y operan números en
forma independiente de la localidad 3.7.4 Date
l Al desplegar los valores con toString se debieran
hacer en el formato de la localidad
l Inglés: 123456.78 Fecha y hora
l Francés: 123 456,78
l Alemán: 123.456,78
l Java provee soporte para realizar tales
conversiones en paquete java.text
l NumberFormat
l DecimalFormat

Clase java.util.Date
3.8 Manejo de
l Útil para manejar datos fecha/hora
l Constructor por defecto entrega fecha actual Excepciones
l Operaciones
l Comparación Excepciones, clasificación,
l Suma lanzamiento y manejadores de
l Formato excepciones
l Clase utilitarias
l java.util.Calendar
l java.text.DateFormat

38
Motivación Concepto de Excepciones
l Cuando ocurren errores es importante que un l Una excepción corresponde a un evento que
programa sea capaz de reaccionar al evento interrumpe el flujo normal de ejecución
(capturarlo) l Cuando ocurre tal tipo de evento en un método, se
l Ejemplo de acciones posibles: lanza (throw) una excepción, creando un objeto
l Notificar al usuario de un error especial que se pasa al runtime para manejar la
l Guardar el trabajo hecho excepción
l Volver a un estado seguro anterior l El runtime busca en el stack el método que maneje
l Terminar limpiamente el programa el tipo de excepción
l Ejemplos de errores: l Si se encuentra se captura la excepción invocando al
l Error en la entrada de datos manejador de la excepción (catch)
l Error en un dispositivo (e.g. Impresora apagada, disco lleno) l Si no se encuentra se termina el programa
l Error en el código

Excepciones:Comparación con
Ventajas de Excepciones Java (1/2)
l Separa el código de manejo de errores del código TipoError leerArchivo(char * m i Archivo) {
normal int errorCode = 0;
int fd;
l Hace más legibles los programas int n;
if ((fd = open(“ miArchivo ”) < 0))
l Propaga errores a través de los métodos que se return ERROR_ABRIR_ARCHIVO;
int n = largo del archivo;
encuentran activos en el stack if (n < 0) {
l Transfiere el control en el anidamiento de invocaciones al close(fd );
return ERROR_LARGO_ARCHIVO;
lugar adecuado para su manejo }
l Permite agrupar errores y diferenciar errores while ((n = read(fd ,...)) > 0)
procesar();
l Una excepción es una clase que se puede derivar if (n != EOF)
return ERROR_LECTURA_ARCHIVO;
}

Excepciones:Comparación Ejemplo: Anidamiento de


con Java (2/2) Excepciones
método1 {
class ejemplo { try {
call método2;
public void leerArchivo( ) throws IOException { 5 } catch (exception) {
try {
File arch = new File("miArchivo"); procesar excepción;
} 4
FileReader in = new FileReader(arch );
int c; }
while ((c = in.read ()) ! = -1)
procesar(c); método2 throws exception { 3
in.close (); call método3;
} catch (IOException) { }
hacer algo; 2
}
método3 throws exception {
}
call leerArchivo ; 1
}
}

39
Jerarquía de Clases de
Excepciones Jerarquía de Excepciones
l En Java toda excepción se deriva de la clase Throwable
Throwable
Throwable
l Existen dos subclase:
l Error. Representa un error interno irrecuperable o
agotamiento de recursos en el sistema de runtime de Java Error
Error Exception
Exception
l Exception. Representa una situación excepcional en el
programa. Existen dos tipos:
l Tiempo de compilación (Derivadas de Exception)
l Tiempo de ejecución (Derivadas de RuntimeException) IOException RuntimeException
.... IOException RuntimeException

Subclases de Exception Tipos de Excepciones


l RuntimeException se debe a un error de programación l Excepciones no verificadas (unchecked)
l mal uso de cast l Excepciones derivadas de la clase Error y
l Acceso a arreglo fuera de límite RuntimeException
l OutOfMemoryError
l Acceso con puntero nulo
l StackOverflowError
l IOException son por algún otro problema: l IndexOutOfBoundsException,
l Leer más allá del final del archivo l ClassCastException
l NullPointerException
l Abrir una URL mal formada
l ...
l etc.
l Excepciones verificadas (checked)
l Otras clases de excepciones
l IOException,
l ClassNotFoundException
l SQLException
l ...

Métodos: Manejo de
Excepciones Cómo lanzar una excepción?
l Un método advierte al compilador sobre excepciones que no
puede manejar lanzándola con throws
l Los pasos son:
l Ejemplo: l Se debe elegir una clase apropiada de excepción
public String leerLinea() throws IOException l Crear un objeto de excepción de esa clase
l Un método debe declarar todas las excepciones verificadas l Lanzar la excepción con throw
(checked)
l Si no declara todas, el compilador reclama l Ejemplo:
l Al declarar una clase de excepciones, entonces puede lanzar
cualquier excepción de alguna subclase throw new ClaseExcepción();
l Aquellas excepciones que son capturadas ( catch) no salen del
método y no debieran ser declaradas
if (ch == -1) { // se encuentra EOF
if (leidos < tamaño)
throw new EOFException();
}

40
Ejemplo: Lanzamiento de Creación de Clases de
Excepción Excepciones
l Si las excepciones estándares no son adecuadas, el
usuario puede definir las propias, derivando alguna clase
public Object pop() throws EmptyStackException { existente
Object obj;
l Es práctica común definir un constructor de omisión y otro
con un mensaje detallado
if (size == 0)
l Ejemplo:
throw new EmptyStackException ();
obj = objectAt(size - 1); class FileFormatException extends IOException {
setObjectAt(size - 1, null); public FileFormatException () {
size--; }
return obj;
public FileFormatException(String msg) {
} super (msg);
}
}

Ejemplo de uso de Excepción Capturando Excepciones


l Sentencia try permite definir un bloque de sentencias para las
public String leer(BufferLectura lector) cuales se quiere definir un manejador de excepciones
throws FileFormatException { l Para cada clase de excepción se define un manejador diferente
... con catch
while (...) {
l Usando una superclase común varias subclases diferentes de
if (ch == -1) { // se encuentra EOF
excepciones pueden tener un único manejador
if (leidos < tamaño)
throw new FileFormatException (); l Forma:
}
... try {
return str; // grupo de sentencias
} } catch (ClaseExcepción1 e) { ...}

} catch (ClaseExcepciónn e) { ...}

Ejemplo: Manejadores de
Excepciones Relanzando una Excepción
Graphics g = imagen.getGraphics();
try {
try {
// código que lanza excepciones
. . .
} catch (MalformedURLException e) {
} catch (ArrayIndexOutOfBoundsException e) {
g.dispose();
System.err.println ("Agarró ArrayIndexOutOfBoundsException : " +
throw e;
e.getMessage());
}
} catch (IOException e) {
System.err.println ("Agarró IOException: " +
e.getMessage()); Relanza la excepción
}
capturada por el
manejador de
MalformedURLException

¡Se podría lanzar también una excepción diferente!

41
Cláusula finally Ejemplo de finally
public void writeList() {
l Cuando se lanza una excepción se detiene el PrintWriter out = null;
try {
procesamiento normal del método System.out.println("Entering try statement") ;
out = new PrintWriter(new FileWriter ("OutFile.txt") ) ;
l Esta situación puede ser un problema si el método ha if (size < 0)
adquirido recursos return;
for ( int i = 0; i < size; i++ )
out.println(" Value at : " + i + " = "
l Se hace necesario disponer de un código de limpieza + victor.elementAt(i));
} catch ( ArrayIndexOutOfBoundsException e) {
l La solución es usar la cláusula finally, que se System.err.println("Caught ArrayIndexOutOfBoundsException: "
+ e.getMessage());
ejecuta haya o no excepción antes de retornar } catch ( IOException e) {
System.err.println("Caught IOException: " + e.getMessage ());
l En caso de capturar una excepción, el código de manejo } finally {
if (out ! = null) {
se ejecuta antes que el de finally System.out.println("Closing PrintWriter" );
out.close ();
l Finally se ejecuta siempre, incluso si se alcanza un return } else
System.out.println("PrintWriter not open ");
en condiciones normales. }
}

Resumen
3.9 Streams y
l El mecanismo de excepciones permite transferir el
control cuando suceden errores en el programa Archivos
l El código de manejo de los errores se puede
separar del código de desarrollo normal Streams, clases, archivos,
l Cada método debe declarar las excepciones streams de objetos y
verificadas (checked) que no puede manejar, de
manera que los programadores sepan al usar la
serialización
clase que excepciones pueden esperar

Streams de Bytes y Caracteres


l E/S es en principio una secuencia de bytes
3.9.1 Streams Básicos l Ejemplo: Archivo, dispositivo, conexión red, etc.
l Java provee dos clases básicas para bytes:
l InputStream : Secuencia de bytes de entrada
l OutputStream : Secuencia de bytes de salida
l Estas clases no son convenientes para manejo de
Unicode (un carácter tiene 16 bits), ∴ se define:
l Reader : Entrada de caracteres Unicode
l Writer : Salida de caracteres Unicode
l De estas cuatro clases abstractas Java deriva las
demás clases

42
API de InputStream (1/2) API de InputStream (2/2)
l abstract int read() l long skip(long n)
l Lee un byte de entrada (retorna -1 se llega al final) l Salta n bytes en la entrada (retorna # de bytes saltados)
l int read(byte[] b) l int avalaible()
l Lee un arreglo de bytes (lee a lo más b.length bytes) l Retorna # de bytes disponibles sin bloquear
l Retorna bytes leídos (retorna -1 si está al final) l void close()
l int read(byte[] b, int off, int largo) l Cierra entrada
l Lee un arreglo de bytes (lee a lo más b.length bytes) l void mark(int lim)
l Retorna bytes leídos (retorna -1 si está al final) l Coloca marca en posición actual. Se borra al leer lim bytes
l off: offset en arreglo b l void reset()
l largo: Máximo # de bytes a leer l Vuelve a posición de última marca
l boolean markSupported()
l retorna verdadero si soporta marcas

API de OutputStream API de Reader y Writer


l abstract void write(int n) l Reader
l Escribe un byte de datos l int read()
l void write(byte[] b) l int read(char cbuf[])
l Escribe todos los bytes en el arreglo b
l int read(char cbuf[], int offset, int largo)
l void write(byte[] b, int off, int largo)
l Escribe largo bytes desde posición off en el arreglo b l Writer
l void close() l int write(int c)
l Cierra la salida l int write(char cbuf[])
l void flush() l int write(char cbuf[], int offset, int largo)
l Vacía la salida (escribe datos mantenidos en buffer)

Conjunto de Streams Subclases de Reader y Writer


l Java provee más de 60 clases de streams
l Todas las clases se derivan de las 4 clases
básicas
l Clases básicas sólo permiten leer o escribir
bytes o caracteres

43
Subclases de InputStream y
OutputStream Composición de Streams
l Los streams se pueden componer para lograr la
funcionalidad deseada
l Ejemplo:
l FileInputStream permite leer bytes desde un archivo
l Java provee algunas clases que permiten ensamblar bytes
en tipos de datos útiles (e.g. DataInputStream y
PrintWriter)
l Java permite combinarlos para lograr, por ejemplo leer
números de un archivo

Ejemplos de Streams de
Filtrado
FileInputStream fin = new FileInputStream(“miArchivo.txt”)
DataInputStream din = new DataInputStream(fin); 3.9.2 Archivos
double d = din.realDouble();

PushbackInputStream pbin = new PushbackInputStream


(new BufferedInputStream
(new FileInputStream(“miArchivo.txt”)));
...
int b = pbin.read();
if (b != “<“)
pbin..unread(b);

Clases Básicas de Archivos Constructores para Archivos


l FileReader. Lectura de caracteres l Las cuatro clases anteriores aceptan tres tipos de
constructores
l FileWriter. Escritura de caracteres l FileInputStream in = new
l FileInputStream . Lectura de bytes FileInputStream (“miArchivo”);

l FileOutputStream . Escritura de bytes l File f = new File(“miArchivo”)


FileInputStream in = new FileInputStream(f);

l FileDescriptorfd = ...;
FileInputStream in = new FileInputStream(fd);

44
Ejemplo: Copia de Archivo Clase File
import java.io.*;
l No corresponde a un stream (se deriva de
public class Copy {
public staticvoid main(String[] args) throws IOException { Object), que permite tener repesentación
File archivoEntrada = new File(”Entrada.txt"); abstracta de archivos y directorios
File archivoSalida = new File(”Salida.txt");

FileReader in = new FileReader(archivoEntrada);


l Está definida en paquete java.io
FileWriter out = new FileWriter(archivoSalida); l Posee métodos tales como:
int c; l Crear directorio, renombrar, borrar, sendero del
while ((c = in.read()) != -1)
out.write(c); FileInputStream in = new archivo, listar directorio, etc.
FileInputStream(archivoEntrada);
in.close(); out.close(); FileOutputStream out = new
} FileOutputStream(archivoSalida);
}

Clase RandomAccessFile Streams y Archivos ZIP


l int skipBytes(int) l Se usan para archivar uno o más archivos en
l Mueve el puntero el # de bytes indicado hacia formato comprimido (GZIP o ZIP)
adelante l Cada archivo tiene un cabecera con información tal
como:
l void seek(long) l Nombre del archivo, método de compresión
l Posiciona el puntero justo antes del byte l Para procesar una entrada se deben leer las entradas
especificado
l Java provee cuatro clases para compresión
l long getFilePointer() definidas en paquete java.util.zip.* :
l Retorna la posición actual del puntero l ZipInputStream. Stream de entrada comprimida
l ZipOutputStream . Stream de salida comprimida
l ZipEntry. Describe una entrada
l ZipFile. Archivo ZIP

Streams de Buffering
3.9.3 Streams
l BufferedInputStream
Especiales l Permite usar buffer de entrada para leer sin
causar un acceso a dispositivo en cada operación
l BufferedOutputStream
l Idem para salida
l PushbackInputStream
l Permite devolver datos al stream

45
Clases DataInput y DataOutput Clase PrintWriter
l boolean void writeBolean(boolean b) l Permite escribir texto formateado
readBoolean () void writeByte(byte b) (no se especifica destinatario)
l byte readByte() void writeChar(char c) l void print(Object)
l char readChar() void writeChars(String s)
l void print(String s)
void writeDouble (double d)
l double readDouble() l void println(Strings)
void writeFloat(float f)
l float readFloat() void writeInt(int i) l void print(char[] s)
l int readInt() void writeLong (long l) l void print(char c)
l String readLine() writeShort(short s) l void print(int i)
l long readLong() l etc.

l short readShort ()
¡Leen y escriben en binario! ¡Java no provee un stream similar para entrada formateada!

Ejemplo de PrintWriter System.in y System.out


l System.out es un PrintStream
PrintWriter out = new PrintWriter (
new FileOutputStream (“miArchivo”)); l System.out.println(“....”);
... l System.in es un InputStream
out.print(“Esta es una prueba ”);
l ¿Cómo leer desde el teclado?
out.print(2002);
... Especifica java.io.BufferedReader br;
destinatario try{

br = new java.io.BufferedReader(
new java.io.InputStreamReader(System.in));
String str = br.readLine();
Java no provee un stream similar para entrada formateada System.out.println("Ud ingreso "+str);

}catch(java.io.IOException ioe ){
}

Resumen 3.10 Diseño de


l Los streams son el mecanismo básico de programas OO
Java para proveer E/S y son parte de java.io
l Streams se pueden componer para lograr el
servicio deseado Patrones de diseño
l Existen herramientas en java.util para apoyar
en el uso de streams

46
Patrones de diseño Factory
l Son formas convenientes de reutilizar código l Una “fábrica” es un patrón que devuelve una
orientado a objetos entre proyectos y instancia de una clase entre un conjunto de
programadores posibilidades dependiendo de la información
l Promueven que los objetos se ocupen solo de “sus proveída.
propios asuntos”. l Generalmente devuelve una clase abstracta
l Un patrón aborda un problema de diseño recurrente o una interfaz.
que aparece en situaciones especificas y que l El programador no sabe que instancia
represente una solución a este. específica esta usando.

1º Ejemplo de Factory (1/4) 1º Ejemplo de Factory (2/4)


l Clase para separar un nombre en dos partes. class FirstFirst extends Namer{ class LastFirst extends Namer{

public FirstFirst(String s) { public LastFirst(String s) {


l Clase base con dos hijas. int i = s.lastIndexOf(" " ); int i = s.indexOf("," );

i f (i > 0 ) { i f (i > 0 ) {
abstract class Namer{ first=s.substring(0, i).trim(); last=s.substring(0,i).trim();

protected String first; last=s.substring(i + 1).trim(); first=s.substring(i+1).trim();

protected String last; } else { } else {

first = " "; last = s;


public String getFirst() {
last = s; first = " ";
return first;
} }
} } }
public String getLast() { } }

return last;
}
}

1º Ejemplo de Factory (3/4) 1º Ejemplo de Factory (4/4)


public static void main(String[] args) {

NameFactory factory = new NameFactory();


public class NameFactory {
Namer namer ;

public Namer getNamer(String entry) {


namer = factory.getNamer("Perez, Juanito") ;
int i = entry.indexOf( ","); System.out.println( "First: " + namer.getFirst());
if (i > 0) System.out.println( "Last: " + namer.getLast());

return new LastFirst(entry);


else namer = factory.getNamer("Maria Espinoza") ;

System.out.println( "First: " + namer.getFirst());


return new FirstFirst(entry);
System.out.println( "Last: " + namer.getLast());
}
}
}
First: Juanito

Last: Perez

First: Maria
Last: Espinoza

47
2º Ejemplo de Factory (1/4) 2º Ejemplo de Factory (2/4)
class NetLogger extends AsbtractLogger{
l Fabrica de objetos para realizar loggin public NetLogger(URL destiny, int minLevel){

l Utilización de configuraciones por defecto super (minLevel);

}
interface Logger{
protected void doLog(String message) {
public void doLog(String message, int level);
System.out.println("[NetLogging]" +message);
}
}
abstract class AsbtractLogger implements Logger{
private int minLevel; }

protected AsbtractLogger( int level){ class FileLogger extends AsbtractLogger{


minLevel=level; public FileLogger(File destiny, int minLevel){
}
super (minLevel);
public void doLog(String message, int level){
}
if(level>=minLevel)
protected void doLog(String message) {
doLog(message);
} System.out.println("[FileLogging]"+message);

abstract protected void doLog(String message); }


} }

2º Ejemplo de Factory (3/4)


public class LoggerFactory {
private int defaultLevel=0;
2º Ejemplo de Factory (3/4)
private String defaultDestiny;
public void setDefaultLevel(int l){defaultLevel=l;} public static void main(String[] args) {
public void setDefaultDestiny(String str) {defaultDestiny = str;}
LoggerFactory factory = new LoggerFactory();
public Logger createLogger(){return createLogger(defaultDestiny);}
factory.setDefaultLevel(2); [NetLogging]test2
public Logger createLogger(String destiny){
factory.setDefaultDestiny("http://log.inf.utfsm.cl") ; [NetLogging]test3
try{
Logger logger1= factory.createLogger(); [NetLogging]test4
URL url = new URL(destiny);
[FileLogging]test2
return new NetLogger(url, defaultLevel); logger1.doLog("test1" , 1 ) ;
[FileLogging]test3
}catch(MalformedURLException mue){} logger1.doLog("test2" , 2 ) ;
[FileLogging]test4
try{
logger1.doLog("test3" , 3 ) ;
File file = new File(destiny);
logger1.doLog("test4" , 4 ) ;
if(file.exists())
Logger logger2 = factory.createLogger("test.log" );
return new FileLogger(file,defaultLevel);
else logger2.doLog("test1" , 1 ) ;

throw new FileNotFoundException(); logger2.doLog("test2" , 2 ) ;


}catch(FileNotFoundException fnfe){} logger2.doLog("test3" , 3 ) ;
return null; logger2.doLog("test4" , 4 ) ;
}
}
}

Singleton 1º Ejemplo de Singleton (1/3)


l Un “singleton” es un objeto que requiere l Spooler de impresión.
tener una sola instancia creada de manera l Solo se permite un numero máximo de
simultanea. instancias.
l Útil para mejorar rendimiento y asegurar
recursos no compartidos.

48
1º Ejemplo de Singleton (2/3) 1º Ejemplo de Singleton (3/3)
public class PrintSpooler { public static void main(String[] args) {

private static i n t instances=0; PrintSpooler ps1,ps2, ps3;


private static i n t maxInstances=2;

private PrintSpooler(){} ps1 = PrintSpooler.newSpooler();

public static PrintSpooler newSpooler(){ if(ps1!=null) System.out.println( "First spooler created" );

if(instances>=maxInstances) else System.out.println("First spooler not created!" );

return null;

else{ ps2 = PrintSpooler.newSpooler();


instances++; if(ps2!=null) System.out.println( "Second spooler created");

return n e w PrintSpooler(); else System.out.println("Second spooler not created" );

} ps3 = PrintSpooler.newSpooler();

public void finalize(){ if(ps3!=null) System.out.println( "Third spooler created" );


instances --; else System.out.println("Third spooler not created") ;

} }

2º Ejemplo de Singleton (1/3) 2º Ejemplo de Singleton (2/3)


l Conexión a la base de datos public class DBConnection {

private static DBConnection instance=null;

l Una sola instancia private static String defaultSetup;

private String setup;


l Se puede mezclar con una fabrica private DBConnection(String s){setup=s;}

public static void setParameters(String str){defaultSetup=str;};

public static DBConnection getConnection(){

if(instance== null )

instance = n e w DBConnection(defaultSetup);

return instance;
}

public void finalize(){

instance= null ;

Patrones de diseño
2º Ejemplo de Singleton (3/3) empresariales
l Principalmente para aplicaciones
public static void main(String[] args) {
distribuidas.
DBConnection dbc1, dbc2;

DBConnection.setParameters("jdbc:oracle:thin:bd.inf.utfsm.cl/db1"); l Incluyen conceptos de J2EE.


dbc1 = DBConnection.getConnection();

dbc2 = DBConnection.getConnection();
l Mantienen complejidad baja y alta
mantenibilidad en sistemas web integrados
if(dbc1==dbc2)

System.out.println("Only one connection" );


con un back-end.
else

System.out.println("More than one connection");

49
View Helper View Helper
l Motivación
l Los cambios en las capas de presentación son usuales.
l Son difíciles de desarrollar y mantener cuando la lógica de
acceso a datos del negocio y la lógica de formatos de
presentación están mezclados.
l Se requiere una separación clara de las tareas
l Solución
l Una vista (View) contiene el código de formato,
delegando las responsabilidades de procesamiento a
una clase que la asiste (Helper).

View Helper Session Facade


l Motivación
l La lógica y los datos del negocio quedan expuestos a los clientes a través
de componente empresariales.
l Esto implica que la capa cliente queda expuesta a la complejidad de las
interfaces de los servicios distribuidos
l Alto acoplamiento, provocando dependencias entre las capas del cliente y
de la lógica.
l Se generan muchas invocaciones de métodos entre el cliente y el servidor,
generando problemas de rendimiento en la red.
l No existe una estrategia uniforme de acceso desde los clientes h acia los
servicios, permitiendo un mal uso de las interfaces de los componentes.
l Solución
l Utilizar un componente en el servidor como una fachada que
encapsula la complejidad de las interacciones entre los componentes
empresariales y el cliente, entregándole a este ultimo una estra tegia de
acceso uniforme de menor granularidad.

Session Facade Session Facade

50
Data Access Object Data Access Object
l Motivación
l Las aplicaciones requieren de datos persistentes

l Además pueden requerir acceder a información que reside en


distintos sistemas.
l Los componentes requieren un acceso transparente al lugar de
almacenamiento persistente o a la implementación específica de
la fuente de datos.
l Solución
l Utilizar un objeto de acceso a datos (Data Access Object,
DAO) para abstraer y encapsular el acceso a la fuente de
datos. El DAO administra la conexión con la fuente de datos
para recuperar y almacenar los datos.

Data Access
Object Ejemplo completo
l DAO para recuperar productos e usuarios
l XML
l Base de datos
l Web service
l Componentes del negocio para listar y
vender productos
l Fachada para encapsular funcionalidad
l Cliente que accede a los servicios

DAO para usuarios DAO para usuarios


class UserDAO {

private User user ;

public class User { public UserDAO(User u){user = u;}

public boolean load() throws SQLException{


private int rut;
int rut = this.user.getPK ();
private String nombre; user.setNombre("pedrito") ;

public User(String n){setNombre(n);} return false;

}
public int getPK(){ return rut; }
public boolean store() throws SQLException{
public void setNombre(String n){nombre=n; } int rut = this.user.getPK ();

} return false;

public static Collection getUsers (){

return null;

}
}

51
DAO para usuarios DAO para productos
public static void main(String args []){ public class Product {

private String code;


User u = new User("111111");
public String getCode(){
UserDAO dao = new UserDAO(u);
return code;
try{
}
dao.load ();
}
u.setNombre(" Juanito");
dao.store(); abstract class ProductDAO{
public abstract Product[] getProducts ();
}catch(SQLException sqle ){}
public abstract Product[] getFilteredProducts(String str);
}
public abstract int getStock(Product p);
public abstract void decrementStock(Product p);
}

DAO para productos


class ProductXMLDAO extends ProductDAO{

public Product[] getProducts( ) {return null; }


DAO para productos
public Product[] getFilteredProducts(String string) {return null ;}
class ProductDAOFactory{
Factory
public i n t getStock(Product p ) {return 0;}
private static String source= "jdbc:postgresql:localhost:5432/myDb";
public void decrementStock(Product p ) {}
private static ProductDAO instance=null;
}

class ProductDBDAO extends ProductDAO{


public static ProductDAO createProductDAO(){
Singleton
if(instance!= null ) return instance;
public Product[] getProducts( ) {return null; }
if(source.equals( "source.xml" ))
public Product[] getFilteredProducts(String string) {return null ;}
instance = n e w ProductXMLDAO();
public i n t getStock(Product p ) {return 0;}
else if(source.equals ("jdbc:postgresql:localhost :5432/myDb") )
public void decrementStock(Product p ) {}
instance = n e w ProductDBDAO( ) ;
}
else if(source.equals ("http: / /localhost:8081/ws" ))
class ProductWSDAO extends ProductDAO{
instance = n e w ProductWSDAO( ) ;
public Product[] getProducts( ) {return null; }
return instance;
public Product[] getFilteredProducts(String string) {return null ;}
}
public i n t getStock(Product p ) {return 0;}
}
public void decrementStock(Product p ) {}

class ProductRetriever{

ProductDAO pDao = null;


Componentes del negocio
public ProductRetriever( ) {

Componentes del negocio pDao = ProductDAOFactory.createProductDAO();

public Product getProduct(String code){


l Un componente para agrupar tareas de Product[] arr= pDao.getFilteredProducts( "code="+code );

recuperación de información. if(arr.length >0) return arr[0];

else
l Un componente para agrupar tareas de throw new IllegalArgumentException

modificación de información. ("The product code doesn't exist! ");

public Collection getProducts (){


Product[] arr= pDao.getProducts( ) ;

...

public Collection getUserProducts(User u){

Product[] arr = pDao.getFilteredProducts ("buyer= "+u.getPK());

...
}

52
Componentes del negocio Fachada de listado y venta
public class ProductFacade {
class ProductManager{ private ProductRetriever retriever=new ProductRetriever();
ProductDAO pDao = null; private ProductManager manager = new ProductManager();

public ProductManager(){ private User loggedUser;

pDao = ProductDAOFactory.createProductDAO (); public ProductBean listProducts(){


...
}
}
public boolean dispatchProduct(Product p, User u){
public boolean sellProduct(String pCode, int quantity ){
if(pDao.getStock(p)>0)
...
pDao.decrementStock(p); }
... public static class ProductBean{

...
}
}
}
}

Fachada de listado y venta: Fachada de listado y venta:


Listado Venta

public ProductBean listProducts(){ public boolean sellProduct(String pCode, int quantity ){


ProductBean bean = new ProductBean (); Product p;

bean.setProducts(retriever.getProducts()); try{
bean.setUserProducts(retriever.getUserProducts(loggedUser )); p=retriever.getProduct(pCode);
return bean; }catch (IllegalArgumentException iae){
} return false;

}
manager.dispatchProduct(p, loggedUser );
return true;

Fachada de listado y venta:


Objeto de transferencia Cliente
public static class ProductBean{
View
public class Client {
private Collection products; ClientView view;
private Collection userProducts;
public void showProducts(){
public Collection getProducts () {
view.showProducts();
return products;
}
}

public Collection getUserProducts () { } Helper


return userProducts;

} class ClientView{

public void setProducts(Collection collection) { private ClientHelper helper = new ClientHelper( ) ;

products = collection ; public void showProducts(){

} Iterator it = helper.getProducts().iterator();

public void setUserProducts(Collection collection) { while (it.hasNext())

userProducts = collection ; System.out.println(it.next());

} }

} }

53
Cliente Conclusiones
l Clara separación de tareas.
class ClientHelper{
private ProductFacade facade = new ProductFacade(); l Posibilidad de distribuir objetos.
public Collection getProducts(){ l Definición de paquetes
Collection c = new Vector();
l Las únicas clases publicas son “User”, “Product” y
ProductBean bean = facade.listProducts();
“ProductFacade”.
c.addAll(bean.getUserProducts());
l El cliente se define en un paquete distinto.
c.addAll(bean.getProducts());
return c ;
l El cliente solo puede acceder a la fachada.
}
}

Resumen
l Factory
l Singleton
l View Helper
l Session Facade
l Data Access Object

54