3.1 Introducción a Capítulo III TDA y OO -...
Transcript of 3.1 Introducción a Capítulo III TDA y OO -...
1
Capítulo III
Tipos de Datos Abstractos, Orientación a Objetos y
Lenguaje Java
3.1 Introducción a TDA y OO
Problemas en el Desarrollo de Grandes Programas
� ¿Cómo organizar una pieza de software, de manera que sea fácil de mantener y administrar?
� ¿Cómo evitar tener que recompilar todo un sistema, en vista de un pequeño cambio?
Modularidad y Reutilización del Software (1/2)
l Ideas:l Organizar el programa en grupos de
subprogramas y datos, lógicamente relacionados, denominados módulos.
l Agrupar en subprogramas que puedan ser compilados de forma independiente, sin necesidad de recompilar todo el sistema.
Modularidad y Reutilización del Software (2/2)
l El proceso de diseñar los módulos o contenedores sintácticos, se denomina modularización.
l Una unidad de compilación es un conjunto de subprogramas que pueden compilarse de manera independiente al resto del sistema
Encapsulación
l Encapsulación: Agrupar un conjunto de subprogramas junto con los datos que ellos manipulan.
l La encapsulación permite resolver los dos problemas presentados.
l Además permite ver los conjuntos como cajas negras.
2
Ventajas de la Encapsulación
l Mayor modularidadl Mejor mantenciónl Permite ser movido
l Ocultamiento de la informaciónl Un objeto provee una interfaz para comunicarse
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
Tipos de Datos Abstractos (TDAs)
l Un TDA, corresponde a una encapsulación que incluye:l La representación de un tipo de dato específicol Las operaciones asociadas a ese tipo
l Una instancia de un TDA se denomina objeto
Ocultamiento de Información
l Mediante control de acceso, detalles innecesarios de la implementación de un TDA se ocultan a aquellas unidades fuera de la encapsulación
l Un cliente es una unidad de programa que hace uso de una instancia de TDA
Ejemplo: Ocultamiento de la Información
public class PruebaUsoStack {
public static void main(String[] args) {Stack st = new Stack(5);
st.push("Hola");st.push(args[0]);String s;while (st.size()>0) {
s = st.pop();System.out.println(s);
}}
}
Problemas de Reuso con TDAs
l Los TDAs son las unidades a reusar, pero:l Generalmente requieren ser adaptadas para el
nuevo usol Hacer las modificaciones implicaría entender los
detalles de implementación del TDA reutilizadol ¿Cómo representar relaciones entre distintos
TDAs?l Por ejemplo: relación padre-hijo (relación de
subordinación) o de similitud de roles
OO en el Diseño de Lenguajes
l OO Puros (e.g. Smalltalk)l OO no purosl mantienen elementos de otros paradigma (e.g.
Java y Eiffel de los imperativos)
l Lenguajes Extendidos a OOl Extensión de imperativo (e.g. C++ y Ada 95)l Extensión de funcional (e.g. CLOS)
3
Visión Computacional OO (PURA)
l Un programa es un conjunto de objetos (instancias de alguna clase), que corresponden a una abstracción del mundo real (problema)
l Un objeto se comunica con otro objeto enviando un mensaje a algún método de este último, el cual le puede retornar otro objeto como resultado
l Procesamiento del mensaje puede alterar el estadodel objeto (sus variables internas).
Soporte para Programación Orientada a Objetos
l Tipos de Datos Abstractosl Clases y Objetosl Concepto de encapsulación
l Herencial Simple y múltiple
l Polimorfismo, con especie particular de ligado dinámico de métodos a mensajesl Clases y métodos virtuales en C++l Uso de interfaces en Java
Objetos
l Un objeto tiene estado y comportamientol El estado se mantiene en variablesl El comportamiento se implementa mediante
métodosl Un objeto encapsula su estado mediante sus
métodos (Abstracción de datos)l Un objeto controla la manipulación de su
estado mediante sus métodos
Objetos (representaciones)
NombreClase
atributo 1 : Integeratributo 2 : Integeratributo 3 : Boolean
Metodo A()Metodo B()Metodo C()
Ejemplo de Objeto: Stack
push()
pop()
size()Estado
Método
Mensajes
l Objetos interactúan enviándose mensajesl Un mensaje consiste en:l Identificador del objetol Identificador del métodol Parámetros (si son necesario)
l Objetos no requieren estar en el mismo proceso o máquina
4
Mensajes
1.- Objetos utilizan métodos para enviar mensajes
2.- Los métodos manipulan el estado interno
Ejemplo de Mensaje
push()
pop()
size()
Stack Spush(“Hola”)
Cliente
Ejemplo: Mensajes a un Objeto en Java
public class PruebaUsoStack {
public static void main(String[] args) {Stack st = new Stack(5);
st.push("Hola");st.push(args[0]);String s;while (st.size()>0) {
s = st.pop();System.out.println(s);
}}
}
Concepto de Clase
l Introducidas en SIMULA 67l Una clase representa a un conjunto de objetos con
características comunesl Un objeto es una instancia de una clasel Una clase es un molde a partir del cual se crean
objetosl Una clase puede tener variables (o campos) y
métodos de clase (comunes para toda la clase)
Clases vs. Objetos
l Una clase define un tipo abstracto de datol Los objetos son instancias de una clase, y por lo
tanto ocupan memoria.l Se les puede instanciar en forma estática, del stack
o del heap (C++ permite las tres formas).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)
Clases: Ejemplo en C++
class complex {private :
float re, i m;public :
complex() { re = im = 0.0;
}float getRealPart();float getImPart();...
}
Campos privados
Campos públicos
Constructor
Operaciones
Datos
int main(void ) {complex cpl; // Crea una instancia de la clase (objeto)cout << cpl.getRealPart();...
}
5
Ejemplo: Implementación de un Stack en Java
public class Stack {private int Maximo ;private int top = -1;private String[] buffer;
public Stack(int i) {Maximo = i;buffer = new String[i ];
}
public void push(String nuevo) {if (top < Maximo-1)
buffer[++top] = nuevo;else System.err.println("Oops, stack lleno");
}
public String pop () {String respuesta = "";
if (top>=0) respuesta = buffer[top--];
else System.err.println("Oops, stack vacio"); return respuesta;
}
public int size () {return top+1;
}
}
Ejemplo: Creación de un objeto de clase Stack
public class PruebaUsoStack {
public static void main(String[] args) {Stack st = new Stack(5);
st.push("Hola");st.push(args[0]);String s;while (st.size()>0) {
s = st.pop();System.out.println(s);
}}
}
Concepto Herencia
l Permite reusar tipos de datos abstractos ya definidos, sin alterarlos.
l La reutilización se realiza definiendo nuevos TDA que modifican o agregan (datos y/o métodos) al TDA de base.
l Por lo tanto, permite adaptar un TDA a las condiciones particulares de un problema con menor esfuerzo
Jerarquía de Herencia
l Un TDA se denomina clase, y las que heredan de una clase base se denominan clases derivadas (o subclases)
l Un TDA se deriva de una clase padre denominada superclasel En Java se habla de extender una clase
Representación de Herencia Usuario
login : Stringpassword : StringNombre : StringclaveDB
getNombre()login()load()
Profesorhoras_de_trabajo : IntegerjefeCurso : String
fijarPrueba()
Administrativocargo : String
marcarTarjeta()
Empleado
sueldo : Integertitulo : String
pagarSueldo()
Secretaria
matricularAlumno()
Director
contratarProfesor()
Portero
limpiarPasillo()
Alumnocurso : Integerpromedio : Single
nuevaAnotacion()nuevaNota()registrarAsistencia()rendirPrueba()
Ejemplo: Herencia en Java
public class StackPrint extends Stack {
public StackPrint(int i) {super(i);
}
public void print () {System.out.println("tamaño: " + (top+1));for (int i=0; i<top+1; i++) {
System.out.println(i + ": " + buffer[i]);}
}
}
public class Prueba {
public staticvoid main(String[] args) {
StackPrint stp = new StackPrint (5);stp.push("Hola-print ");stp.push(args[0]);stp.print ();
}
}
6
Herencia: Relaciones entre clases
l El mecanismo de herencia permite extender una clase (agregar variables o métodos)
l Si B extiende a A, entonces B hereda todo lo de A (la superclase), siendo la clase heredera B una subclase de A
l Una subclase heredera puede implementar a su manera un método heredado (override)
Ventajas de la Herencia
l Subclases proveen comportamiento especializado en base a la superclase
l Los programadores pueden definir clases abstractas, que definen un comportamiento genérico, que debe ser específicamente definido por las clases herederas
l En resumen, representan un mecanismo de reutilización de interfaces y código
Herencia Múltiple
l La nueva clase hereda sus propiedades a partir de dos o más clases
Clases bases
...
Subclase
Problemas con Herencia Múltiple
l Colisión de nombres introduce una complicación
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 mantención de sistemas, considerando la mayor complejidad de organización
Polimorfismo mediante Ligado Dinámico de Métodos
l Permite crear variables del tipo de la clase del padre que pueden referenciar objetos de cualquier subclase (polimorfismo )
l Las subclases pueden tener métodos que llevan el mismo nombre del padre, pero que las subclases las adaptan con otra implementación (override)
l Cuando se invoca un método de este tipo, se debe dinámicamente hacer el ligado al método que corresponde (dynamic binding).
Ejemplo: Ligado Dinámico de Métodos
Datos
Datos Datos
Figura
Triángulo Cuadrado
dibujar
dibujar dibujar
rotar
rotar rotar
7
Clases y Métodos Virtuales
l A veces, la jerarquía de clases hace que para una clase particular, no tenga sentido la creación de objetos.
l En tal caso, la clase puede definir el prototipo de métodos genéricos que son implementados en todas las clases derivadas.l Tales métodos se denominan métodos virtuales.l La clase que posee estos métodos se denomina clase
virtual.l Los métodos virtuales pueden tener una implementación
por defecto.
Polimorfismo en C++class figura { // ... public: virtual void rotar (int) = 0; virtual void dibujar (void) = 0; // ... }; class circulo: public figura { real radio; public: void rotar (int) {} // anula figura::rotar void dibujar (void); // anula figura::dibujar circulo (punto p, real radio); };
figura *f[100]; ... for (int i=0; i<n; i++) f[n]->dibujar();
Interfaces en Java
l Define un protocolo de comunicación para la interacción de objetos sin necesidad de conocer su clase (especie de polimorfismo)
l Una o más clases pueden implementar una misma interfazl Una clase que implementa una interfaz debe
necesariamente implementar cada método de la interfaz
Ejemplo: Interfaz en Java
public interface StackInterface { void push(String s);String pop();int size();
}
public class StackImp implements StackInterface {private int Maximo;protected int top = -1;protected String[] buffer;
public StackImp(int i) {Maximo = i;buffer = new String[i];
}// .....
}
Utilidad de una Interfaz
l Captura similitudes entre clases no relacionadas sin forzar artificialmente una relación entre ellas
l Declarar métodos que una o más clases esperan implementar
l Revelar una interfaz de programación sin revelar las clases que la implementan
3.2 Introducción a Java
Historia, características, lenguaje y entorno de Java
8
Orígenes del Lenguaje Java
l 1991. James Gosling inicia proyecto para escribir código independiente de plataforma para sistemas empotrados. Intenta con C++, pero no le satisface
l 1993. Desarrolla un nuevo lenguaje llamado OAK, similar a C++, pero portable y seguro
l 1994. Aparece WWW y Mosaicl 1995. Sun anuncia disponibilidad de lenguaje Java
y browser HotJava, que soporta appletsl 2004. Versión J2se1.5-Beta disponible. Incluye
programación genérica como parte del lenguaje
Tecnología Java
l Lenguaje de Programaciónl Orientado a objetosl Sintaxis similar a C++
l Plataformal Máquina Virtual Java (JVM)l Java APIl Tres versionesl J2SEl J2EEl J2ME
Características del Lenguaje Javal Simple y orientado a objetosl Simple de aprender, alta reutilización y bibliotecas
l Robusto y segurol Tipificación fuerte, recolección de basura
l Interpretado, neutro de la arquitectura y portablel Se compila en bytecode, interpretado por JVM
l Distribuido y alto desempeñol Movilidad de código y permite tb. compilación JIT
l Multi-hebral Mejora la interactividad de la aplicaciones
l Dinámicol Permite enlace y carga dinámica de clases
Proceso de Desarrollo en Java
public class HolaMundoApp {publicstaticvoid main(String[] args) {
// Desplegar "Hola Mundo!"System.out.println(" Hola Mundo!");
}}
Programa Java
HolaMundoApp.java
Compilador
JVM
HolaMundoApp.class
JVM JVM
WindowsSolaris Linux
Genera bytecode
Aplicación Java
l Le dice al sistema que ejecute la función main de alguna clase
l Carga dinámicamente otras clases que requiera
l Aplicaciones son consideradas confiables(no significa que lo sean)l Pueden leer, escribir, crear o borrar archivos
Un Primer Programa de Aplicación
/*** La clase HolaMundoApp implementa una aplicación* que despliega por la salida estándar “Hola Mundo”
*/
public class HolaMundoApp {public staticvoid main(String[] args) {
// Desplegar "Hola Mundo!"System.out.println(" Hola Mundo!");
}}
9
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)
Método main
l Cuando se ejecuta una aplicación Java, el interpretador invoca a mainl Si no existe se genera un error
l main tiene un argumento único, un arreglo de stringsl Permite al ambiente de ejecución pasar
parámetros a la aplicaciónl Por ejemplo en la línea de comando
Acceso a Recursos del Sistema
l Java provee una API (Application ProgrammingInterface) que permite acceder a recursos en forma independiente del entornol E/S, reloj, etc.
l La API viene definida en el paquete System
Programa Java
System
Entorno de Ejecución
Ejemplo de uso de System
class TestNombreUsuario {public staticvoid main(String[] args) {
String nombre;nombre = System.getProperty ("user.name");System.out.println(nombre);
}}
Applets
l Significa “aplicacioncita”, que lo diferencia de una aplicación normal
l Uso normal es en un Web Browserl También se puede ver con appletviewer
l Proceso de compilación similar al anterior, pero diferente modelo de ejecución
10
Modelo de Ejecución del Applet
BrowserServidor
Web
JVM
Applet
�
�
Applet
Programando un Applet
import java.applet.*;import java.awt.*;
/*** la clase HolaMundo implementa una applet que* simplemente despliega ”Hola Mundo!".*/public class HolaMundo extends Applet {
public voidpaint(Graphics g) {// Display"Hello World!"g.drawString(”Hola Mundo!", 50, 25);
}}
Página Web que Carga Applet
<HTML>
<HEAD><TITLE>Un Programa Simple con Applet</TITLE></HEAD>
<BODY>Aqui viene la salida del programa:<APPLET CODE="HolaMundo.class" WIDTH=150 HEIGHT=25></APPLET></BODY>
</HTML>
Importación de Clases y Paquetes
l La palabra import permite importar clases de un paquetel En el ejemplo import java.applet:* permite utilizar
todas las clases del paquete java.appletl En el ejemplo anterior Applet es una clase del
paquete java.applet
Definición de Subclases
l La palabra extends permite definir una subclase a partir de otra (herencia)l En el ejemplo:
public class HolaMundo extends Applet { ...
Implementación de Métodos
l Una clase puede implementar uno o más métodosl En el ejemplo:
public void paint(Graphics g) {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
11
Funcionalidad de Java (1/2)l Esenciall Objetos, strings , números, E/S, estructuras de datos,
propiedades del sistema, fecha, hora, etc.l Interfaces gráficasl AWT, Swing, Java2d y Java3d
l Comunicación en la Red y Appletsl Web, URL, sockets UDP y TCP, direcciones IP
l Internacionalizaciónl Programas pueden adaptarse al lugar e idioma
l Seguridadl Firma digital, gestión de claves, certificados, control
de acceso, etc.
Funcionalidad de Java (2/2)
....l Threads (hebras)l Programación con múltiples threads
l Componentes de Software (JavaBean)l Se pueden enchufar en arquitecturas existentes
l Serialización de Objetosl Permite persistencia liviana y comunicación via RMI
l Acceso uniforme a base datos relacionesl Usan JDBC (Java Database Connectivity)
Java 2 SDK 3.3 Conceptos Básicos del Lenguaje
Java
Conjunto de Caracteres
l Java utiliza Unicode, un conjunto de caracteres de 16 bits
l Java permite leer ASCII de 7-bit o Latin-1, conviertiéndolo a Unicode
l Son pocos los editores actuales que soportan Unicodel Se puede usar su código en formato \udddd,
donde d es un dígito hexadecimal
Identificadores
l Deben comenzar con una letra, incluido _ o $, seguido de letras o dígitosl Letras en Unicode es un concepto más ampliol Son válidos: Árbol, Hähnchen, etc.
l Se diferencia mayúscula de minúsculal árbol es diferente a Árbol
l Java define algunas palabras reservadas que no pueden ser usadas como identificador
12
Palabras Resevadasl abstractl booleanl breakl bytel casel catchl charl classl constl continuel defaultl do
l doublel elsel extendsl finall finallyl floatl forl gotol ifl implementsl importl instanceof
intinterfacelongnativenewpackageprivateprotectedpublicreturnshortstatic
superswitchsynchronizedthisthrowthrowstransienttryvoidvolatilewhile
Variables, Constantes y Tipos Primitivos
Variable
l Una variable es un item de datos nombrado por un identificador
l Una variable tiene un tipo, que debe ser declarado antes de su uso (como en C)l tipo variable
l Una variable tiene un ámbito (scope), definido por la visibilidad que tiene la variable en el programa
Tipos de Datos
l Un tipo define los posibles valores para una variablel Java define dos categorías de tipos de datos:l Primitivos. Contiene un único valor de tamaño y formato
apropiado (e.g. Entero, real, booleano, etc.)l Referencias. Es una dirección a un conjunto de valores
(e.g. Arreglo, clase e interfaz)
l Las direcciones son implícitas, dado que Java no soporta punteros
Tipos de Datos Primitivos
Tipo Descripción Largo/Formatobyte Entero de un byte 8 bits, C-2short Entero corto 16 bits, C-2int Entero 32 bits, C-2long Entro largo 64 bits, C-2float Punto flotante de
precisión simple32 bits, IEEE 754
double Punto flotante deprecisión doble
64 bits, IEEE 754
char Caracter 16 bits, Unicodeboolean Booleano (true y false)
Más sobre Datos Primitivos
l Cada tipo primitivo (excepto short y byte) tiene una clase declarada en el paquete java.lang
l Constantes declaradas:l MIN_VALUE y MAX_VALUEl NEGATIVE_INFINITY y POSITIVE_INFINITYl NaN (Not a Number)
13
Constantes de Datos Primitivos
l 178 Enterol 178L Largol 345.125 doble prec.l 234.12D doble prec.l 234.12F simple prec.l 23.7e-4 doble prec.l ´c´ caracterl true booleano
Constantes Literales
l 178 Enterol 178L Largol 045 octall 0X45df Hexadecimal
l 345.125 doble prec.l 234.12D doble prec.l 234.12F simple prec.l 23.7e-4 doble prec.
l ´c´ carácterl \n nueva líneal \u8f4d Unicodel true booleano
Declaración de Variables
l [modificador] tipo variable {, variable}*l Modificador es opcionall Posibles modificadores: static o finall static sólo se puede usar en campos (fields) l Ejemplo: float[] x, y;
l Declaraciones pueden aparecer en cualquier parte del código
l La visibilidad de una variable se limita al bloque en que se declara
Orden de Resolución de Nombres
l Declaración local a un bloque (e.g. Loop)l Parámetro de un constructor o métodol Un miembro de una clase o interfazl Tipos explícitamente importadosl Otros tipos declarados en el mismo paquetel Tipos importados implícitamente nombradosl Paquetes disponibles en el sistema host
Valores Iniciales
l Una variable se puede inicializar en su declaraciónl Ejemplo:l final double π = 3.14159;
l Java asigna valores por omisión a los campos de una clase si no se especifical 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
Operadores
14
Precedencia y Asociatividadde Operadores
l A igual precedencia, se asocia por la izquierda, excepto asignación que es por la derecha
l La precedencia se pueda cambiar usando paréntesis
l Para legibilidad se recomienda usar paréntesis, cuando sea posible, de manera de hacer explícita la precedencia, sin exagerar
l Ejemplo:while ((v = stream.next()) != null)
procesar(v);
Precedencia de Operadores (1/2)
Unario posfijo [] . (param) ++ --
Unario prefijo ++ -- + ~ !Creación y cast new (tipo) expMultiplicativo * / %Aditivo + -Shift << >> >>>Relacional < > >= <= instanceofIgualdad == !=
Men
or p
rece
denc
iaPrecedencia de Operadores (2/2)
l AND al bit &l OR exclusivo al bit ^l OR inclusivo al bit |l AND lógico &&l OR lógico ||l Condicional ?:l Asignación = += -= *= /= %=
>>= <<= >>>= &=^= |=
Men
or p
rece
denc
ia
Expresiones
l Una expresión se evalúa de izquierda a derechal Orden puede ser importante cuando existen efectos
laterales o corto-circuito
l En general, cada operando se evalúa antes de realizar la operación
l Cada expresión tiene un tipol En general domina el operando de mayor rango de valores
(e.g. double + long → double)
Conversión de Tipo: Implícita
l Conversión implícita. ¡Es automática!l Valores Primitivos. Se permite entre valores primitivos
cuando se soporta un mayor rango de valoresl No se permite de punto flotante a enterol En la conversión se puede perder precisión
l Referencias. Una referencia a un objeto de una clase incluye una instancia de cada supertipol Se puede usar una referencia a un objeto de un tipo
cuando se requiera una referencia a un supertipo
Conversión de Tipo: Explícita
l Se requiere cuando un tipo no se puede asignar a otro por conversión implícita
l La conversión explícita se denomina castl Ejemplo:
double d = 7.99; long l = (long) d;l Se puede usar para referencias a objetos con
conversión no segural Operador instanceof permite verificar se se
puede aplicar cast a un objetoif (obj instanceof clase) ....
l null instanceof tipo es siempre falso
15
Operadores Aritméticos
l Se soporta para todos los tipos de númerosl Suma +l Resta -l Multiplicación *l División /l Residuo o módulo %
l Además cambio de signo -
Operadores de Incremento y Decremento
l Operador de incrementol a++ equivale a a = a+1
l Operador de decrementol a-- equivale a a = a-1
l Ambos operadores existen en forma prefija y postfijal Prefijo calcula primero la operación y luego se aplica;
postfijo es al revésl Ejemplo: arreglo[i++]
Operadores Relacionales
l Mayor que >l Mayor o igual que >=l Menor que <l Menor o igual que <=l Igual que ==l Diferente !=
Operadores al Bit
l AND al bit &l OR inclusivo al bit |l OR exclusivo al bit ^l Corrimiento a la izquierda <<
(rellenando con 0)l Corrrimiento a la derecha >>
(rellenando con el signo)Corrimiento a la derecha >>>(rellenando con 0)
Operador Condicional
l La formavalor = test ? exp1 : exp2;
l Es equivalente a:if (test)
valor = exp1;else valor = exp2;
l La diferencia es que el operador condicional define valor y permite expresiones más compactas
Operador de Asignación
l El operador = corresponde a la asignación, operador de menor precedencia
l Java soporta otras formas de asignaciónl += -= *= /= %= >>= <<= >>>= &=
^= |=
l Ejemplo:l arreglo[indice()] += 12 es casi equivalente a
arreglo[indice()] = arreglo[indice()] + 12l Segundo caso llama dos veces a indice()
16
Control de Flujo
Sentencias y Bloques
l Un bloque básicamente se compone de:l Sentencias de expresiónl Asignaciónl 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ónl Variables requieren de inicialización
l Toda sentencia se termina con ;l Un bloque se forma con { y }
Sentencia if-else
l Forma básica de flujo de control condicional
if (exp-booleana)sent1
else sent2l El else se parea con el ifmás cercano
if (valor >= 0)if ( valor < MAX)
process(valor);else System.out.println (“valor negativo ”)
Mal asociadoel else
Sentencia switch
l Evalúa una expresión entera cuyo valor se usa para seleccionar caso mediante etiqueta
l Si no se encuentra etiqueta se salta a defaultl Si no existe default, no se hace nada
switch (valor) {case 0: case 2: case 4: case 6: case 8:
System.out.println (“es par”);break;
case 1: case 3: case 5: case 7: case 9:System.out.println (“es impar”);break;
default: System.out.println (“es impar”);}
Sentencia while y do-while
l Permite repetición controlada por expresión boolena
l Las dos formas son:
while (exp-boolena )sentencia
dosentencia
while (exp-boolena );
Sentencia for
l Permite controlar una repetición para un rango de valores
l La forma es la siguiente:
l Esta forma equivale a:
for (exp-inicial; exp-boolena; exp-incremento)sentencia
exp-inicial;while (exp-boolena ) {
sentenciaexp-incremento;
}
17
Sentencia break
l Permite salir desde cualquier bloque, no sólo switch
l Se usa para terminar una repetición como for, while o do
l Se puede usar una etiqueta para salir de un anidamiento de bloques
buscar:for(y=0; y<MAX; y++) {
for (x=0; x<MAX, x++) {if (Matriz[x][y] == valor) {
encontrado = true;breakbuscar;
}}
}if (! encontrado)
System.out.println (“no está”);
Sentencia continue
l La sentencia continue permite saltar al final del cuerpo de una repetición y evaluar la condición de término
l Se usa para ignorar una elemento de proceso
while (! stream.eof ()) {elem = stream.next();if (elem == “ “ || elem == “ \n”)
continue;procesar(elem);
}
Sentencia return
l Permite terminar la ejecución de un método y retorna al invocador.l Si no retorno valor: return;l Si retorna valor: return valor;
3.4 Clases y Objetos
Clases, miembros, constructores, control de acceso
Conceptos Generales
l Las clases contienen los métodos que definen la computación
l Los campos (fields) o variables miembros definen el estado
l Las clases proveen la estructura para los objetos y el mecanismo para su creación
l Un método tiene una firma, pero su implementación define su semántica
l Los métodos definen una suerte de contrato sobre lo que hace un objeto de la clase
Estructura de una Clase
public class Persona {private int ID;privateString Nombre;
public Persona (String s, int id) {Nombre = s; ID = id;
}
public String miNombre(int id) {if (id == ID)
return Nombre;else return null;
}}
Nombre de la clase
Variablemiembro
Cons-tructor
Controlde
Accesodel
miembroImplemen-tación delmétodo
Firma del método
18
Modificadores de la Clase
l publicl Por omisión una clase sólo es accesible por
clases del mismo paquete, salvo que sea declarada pública
l abstractl La clase no puede ser instanciada
l finall La clase no puede ser derivada
Variables Miembrosl Las variables de clases se denominan tb. camposl Cada objeto de una clase tiene sus propias instancias de cada
variable miembrol Significa que cada objeto tiene su propio estadol Cambio de estado en un objeto no afecta a otros objetos
similaresl Variables miembros se pueden compartir entre todos los objetos
de una clase con el modificador staticl Todos los objetos de una clase comparten una única copia de
un campo declarado como staticl En general, cuando se habla de variables y métodos miembros
se refiere a aquellos no estáticos
Ejemplo de Variable Miembro Estática
class Persona {privatestatic int nextID = 0;private int ID;private String Nombre;
public Persona (String s) {ID = ++nextID;Nombre = s;
}
public int getID() {return ID;
}}
VariableEstática(o de Clase)
Control de Acceso de Miembros
l Todos los métodos y variables miembro están disponibles para el código de la propia clase
l Para controlar el acceso a otras clases y subclases, los miembros tienen 4 posibles modificadores:l Privado: Declarados con private son sólo accesibles por la
propia clasel Paquete: Miembros sin modificador de acceso son sólo
accesibles por código y heredados por subclases en el mismo paquete
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
l Se han declarados dos referencias a objetos de clase Persona
l La declaración de una variable no crea un objeto, sino que una referencia a un objeto, que inicialmente es null
l Cuando se usa el operador new, el runtime crea un objeto, asignando suficiente memoria, e inicializando el objeto con algún constructor
l Si no existe suficiente memoria se ejecuta el recolector de basura (garbagge collector ), y si aun no existe suficiente memoria, se lanza la excepción OutOfMemoryError
l Terminada la inicialización, el runtime retorna la referencia al nuevo objeto
Persona p1;Persona p2 = new Persona(“Pedro”);
Constructoresl Un objeto recién creado debe inicializar las
variables miembrol Las variables miembro pueden ser inicializadas
explícitamente en la declaraciónl Muchas veces se requiere algo másl Ejemplo: ejecutar código para abrir un archivo
l Los constructores cumplen ese propósito, tienen el mismo nombre de la clase y pueden recibir parámetros
l Los constructores no son un método (no retornan un valor)
l Una clase puede tener varios constructores
19
Ejemplo de Constructor
class Persona {privatestatic int nextID = 0;private int ID;private String Nombre;
public Persona (String s) {ID = ++nextID;Nombre = s;
}
public int getID() {return ID;
}}
Constructor
Razones para usar Constructores
l Algunas clases no tienen un estado inicial razonable sin inicialización (e.g. tope = -1)
l Proveer un estado inicial conveniente y razonable (e.g. Nombre = “Juan”)
l Construir un objeto puede ser costoso(e.g. objeto crea tabla interna a la medida)
l Por motivos de seguridad de acceso (e.g. constructores pueden ser privados o protegidos)
l Si no se define un constructor, el compilador agrega uno por defecto.
Control de Acceso de Constructores
l privatel Ninguna otra clase puede instanciar la clase (e.g. Clase
fábrica)l protectedl Sólo subclases de las clase y clases del mismo paquete
pueden crear instanciasl publicl Cualquier clase puede crear una instancia
l Sin Especificador (acceso de paquete)l Sólo clases del mismo paquete y de la misma clase
pueden crear instancias
Constructor por Omisión (default)
l Si no se define constructor, se asume un constructor sin argumentos, que no hace nada
l Este constructor por omisión se asume que existe, si no se ha definido un constructor sin argumentos
l El constructor por omisión es público si la clase lo es, sino no lo es
Ejemplo de Múltiples Constructores
class Persona {private static int nextID = 0;private int ID;private String Nombre;private int edad = -1;
public Persona (String s) {ID = ++nextID;Nombre = s;
}
public Persona(String s, int ed) {this(s );edad = ed;
}
//... Otros métodos}
Segundoconstructor
InvocaConstructor
anterior
Métodos
l Un método se entiende para manipular el estado del objeto (variables miembro)
l Algunas clases tienen variables miembro públicas, lo que permite su manipulación directa por otros objetos, pero no es seguro
l Cada método se llama con la siguiente sintaxis:referencia.metodo(args)
l Java no permite un número variable de argumentos como C o C++
20
Métodos: Valores de Parámetros
l En Java todos los parámetros se pasan por valor (tanto primitivos como referencias)l Es decir, se pasa una copia del dato al método
l Si el parámetro es una referencia, es la referencia la que se copia, no el objetol Por lo tanto, un cambio de estado del objeto
referenciado realizado por el método será visible después del retorno
Control de Acceso con Métodos
l Para proteger campos de un acceso externo se usa el modificador private
l Java no provee un modificador que sólo permita lectura de un campo
l Para asegurar acceso de sólo lectura se debe introducir un nuevo método que lo haga indirectamente y en forma segural Este tipo de métodos se denominan accesor
l Es recomendable usar accesores para proteger el estado de los objetos
Ejemplo: Método Accesorclass Persona {
privatestatic int nextID = 0;private int ID;private String Nombre;private int edad = -1;
public int getID() {return ID;
}
public String getNombre() {returnNombre;
}
//... Otros métodos}
Métodoaccesor
Referencia this
l Sólo se puede usar en un método no estático, y se refiere al objeto actual sobre el que se invocó el método
l Implícitamente se usa thisal comienzo de cada miembro propio referenciado por el códigol Ejemplo: En el ejemplo anterior
public int getID() {return ID;
}
Se refiere a:this.ID
Usos de this
l Se usa usualmente para pasar una referencia del objeto actual como parámetro a otro métodol Ejemplo: Timer.wakeup(this, 30);
l Otro uso es cuando existe ocultamiento de una identificador debido a colisión de nombresl Ejemplo
l Similarmente a lo anterior, para tener acceso a miembros ocultos de una superclase (por redefinición: overriden), se puede usar super
public SetEdad (int edad) {this.edad= edad;
}
Usos de thispublic class Padre {
private String nombre;private Hijo primogenito;
public Padre(String n){nombre=n;
}public String getNombre(){
return nombre;}public void nuevoHijo(Hijo h){
primogenito=h;primogenito.asignarPadre(this);
}}
21
Usos de thisclass Hijo{
private String nombre;
private int edad;
private Padre papa;
public Hijo(String n, int e){
nombre=n;edad=e;
}
public void asignarPadre(Padre p){
papa=p;
}
public String nombrePadre (){
if(papa== null )return "N.N .";
else return papa.getNombre();
}
}
Usos de this
public static void main(String[] args) {Padre p = new Padre("Anakin");Hijo h = new Hijo("Luke", 10);System.out.println(h.nombrePadre());p.nuevoHijo(h);System.out.println(h.nombrePadre());
}
N.N.Anakin
Sobrecarga de Métodos
l Cada método tiene una firma (signature):l Nombre del métodol Número y tipos de parámetrosl El tipo de retorno
l Java permite tener varios métodos con un mismo nombre, pero diferentes parámetrosl Se denomina sobrecarga (overload)
l Cuando se invoca un método sobrecargado, se calza con los parámetros usados
Miembros Estáticos
l Un miembro estático es único para toda una clase, en vez de tener uno por objeto
l Variable miembro estática. Existe una única variable para todos los objetos de una clasel Se deben inicializar antes de que se use cualquier
variable estática estática o método de la clase
l Método Estático. Se invoca en nombre de toda la clasel Sólo puede acceder a miembros estáticos (e.g. no
permite usar this)l Se invocan típicamente usando nombre de la clasel Se denominan también métodos de clase
Ejemplo: Método Estático
public class PruebaUsoStack {int x=0;public static void main(String[] args) {
Stack st = new Stack(5);
st.push("Hola");st.push(args[0]);String s;while (st.size()>0) {
s = st.pop();System.out.println(s);
}System.out.println(x );
} }
ClaseSystemmiembro estático out
estático
ERROR
Bloques de Inicialización Estática
l Permiten a una clase inicializar variables miembro estáticas u otros estados necesarios
l Se ejecutan dentro de una clase en el orden que aparecen declarados
l Ejemplo:class Primos {
protected staticint [] PrimosConocidos = new int [4];
static {PrimosConocidos[0] = 2;for (int i = 1; 1 < PrimosConocidos.length; i++)
PrimosConocidos[i] = ProximoPrimo();}
}
22
Recolección de Basura
l Java realiza recolección automática de basura, i.e. el programador no requiere liberar explícitamente los objetosl Sólo existe new (no delete como C++)l Objeto que se detecta sin referencia, el sistema lo libera
l Ventajasl No requiere invocar al administrador de memoria para
liberar cada objetol No se produce el problema de dangling
Método finalize
l Permite ejecutar un método de finalización antes de liberar memoria
l Es el equivalente al concepto de destructor en C++l Es útil cuando se usan recursos no de Java y que
deben liberarse (evitar fuga de recursos)l Ejemplo: Cerrar archivos abiertos
l Forma de declararlo:
protected void finalize() throws Throwable {super.finalize();// ...
}
Ejemplo de finalizepublic class ProcesarArchivo {
private Stream Archivo;
publicProcesarArchivo (String nombre) {Archivo = new Stream(nombre);
}// ...publicvoid close() {
if (Archivo != null) {Archivo.close();Archivo = null;
}
protected void finalize() throws Throwable {super.finalize();close();
}}
Método main
l El método main se debe encontrar en cada aplicación Java
l El método debe ser público, estático y voidl EL argumento único es un arreglo de String,
que se consideran los argumentos del programa
Ejemplo
class Echo {public staticvoid main (String[] args) {
for (int i = 0; i < args.length; i++)System.out.print(args[i] + “ “);
System.out.println();}
>java Echo que argumentos recibeque argumentos recibe
>
La ejecución del programa:
El archivo fuente Echo.java
Método toStringl Si un objeto soporta el método publicString toString(),
este método se invoca en cualquier expresión en que el objeto aparezca con los operadores + y +=
l Ejemplo: class Persona {private int ID;private String Nombre;
public String toString() {return ID + “ : “ + Nombre;
}//... Otros métodos
}
Persona p; //...System.out.println (“La persona” + p);
Ejemplo de uso
23
Métodos Nativos
l Permite que programas Java usen código no escrito en Java l Se implementa el método en lenguaje nativo (e.g.
C ó C++)l El método se invoca desde Javal Se pierde la portabilidad y seguridad de Java
l Se aplica para manipular hardware
Clases Anidadas
l Java permite definir una clase como miembro de otra clase
l Útil cuando una clase tiene sólo sentido en el contexto específico de una clase
l Clase anidada tiene acceso total a todas los miembros de la clase a que pertenece (como lo haría cualquier otro método miembro de la clase superior)
Clases Internas
l Si clase anidada se declara estática, se llama clase anidada estátical No tiene acceso a miembros no estáticol Permite sólo relacionar clases (no instancias)
l Si no es estática, es una clase internal No puede definir miembros estáticosl Permite crear objetos de la clase interna dentro de la clase
a que pertenecel Permite relacionar objetos de las clases relacionadasl Puede ser pública o privada
Ejemplo de Clase Interna
public class Stack {private Vector items;
// código de métodos y constructores de Stack
public Enumeration enumerator() {return new StackEnum();
}
// aquí viene declaración de clase interna// ...
class StackEnum implements Enumeration {int itemActual = items.size() - 1;
publicboolean hasMoreElements() {return (ItemActual >= 0);
}
publicObject nextElement () {if (!hasMoreElements())
thrownew NoSuchElementException();else
return items.elementAt(ItemActual--);}
}
} // fin de declaración de Stack
Resumen
l Objeto y Clasel Miembros (métodos y variables)l Creación de objetos y constructoresl Control de accesol Sobrecarga de métodos y constructoresl Miembros estáticosl Métodos especiales (finalize, main, toString)l Clases anidadas
3.5 Herencia
Extensión de clases, redefinición de miembros, constructores,
clases y métodos abstractos, clase Object
24
Conceptos Preliminares
l En general, una clase define un contrato de uso a través de sus miembros accesibles y el comportamiento esperado de los métodos
l Una clase extendida agrega funcionalidad, creándose una nueva clase, con un contrato extendidol No se cambia el contrato que se hereda de la
superclase, sino que se extiendel Si se puede cambiar la implementación de algunos
métodos heredados, pero respetando el contrato de la superclase
Clases Extendidas
l En Java todas las clases son extendidasl Toda clase se deriva (quizás indirectamente) de la clase
Objectl La clase Object implementa el comportamiento que
requiere todo objeto Javal Java sólo permite tener una única superclase
(herencia simple)l Si no se especifica extends se supone que se deriva de
Object
Ejemplo: Clase Extendida
public class StackPrint extends Stack {
public StackPrint(int i) {super(i);
}
public void print() {System.out.println("tamaño: " + (top+1));for (int i=0; i<top+1; i++) {
System.out.println(i + ": " + buffer[i]);}
}
}
Superclase
Constructorde la Superclase
Reglas de Herencia
l Una subclase hereda todos los miembrosl protegidosl Públicosl Sin modificador (paquete) mientras la subclase se declare
en el mismo paquetel Colisiones de nombresl En el caso de una variable miembro, ésta se ocultal En el caso de un método, éste es redefinido (overriden)
Redefinición de Variables Miembros
l Los campos no se pueden realmente redefinir, sólo pueden ser ocultados
l Si se declara un campo con el mismo nombre de uno de la superclase, este último sigue existiendo, pero no es accesible directamente desde la subclase
l Para accederlos se puede usar referencia super
Ejemplo de Ocultamiento:Variables Miembros
class SuperClase {Number numero;
}
class SubClase extends SuperClase {Float numero;
}
Acceso a SuperClase en SubClase: super.numero
25
Redefinición (overriden) de Métodos (1/3)
l Para la definición de métodos donde existe coincidencia de nombres:l Sobrecarga: Definir más de un método con el mismo
nombre, pero con diferente firmal Redefinición . Reemplaza la implementación de la
superclasel Firma y tipo del retorno deben ser idénticas l Permite modificar o complementar el comportamiento
de un método de la superclasel Se puede invocar el método redefinido desde la
superclase con la referencia super
Redefinición (overriden) de Métodos (1/3)
public class Traductor {public String traducir(String palabra){
...}
}
class MultiTraductor extends Traductor{public String traducir(String palabra, String idioma){
...}
}
class TraductorMandarin extends Traductor{public String traducir(String palabra){
...}
}
class TraductorMapudungun extends Traductor{public String traducir(String palabra){
...}
}
Redefinición (overriden) de Métodos (3/3)
l Un método redefinido sólo puede dar más acceso, no menosl Ejemplo: un método público de la superclase no se puede
declarar privado en la subclasel Métodos que no se pueden redefinir:l Métodos finalesl Métodos estáticos (de la clase): si lo puede ocultar
declarando un método con la misma firma
l Métodos que se deben redefinir:l Métodos que han sido declarados abstractos en la
superclase
Ejemplo de Redefinición de Miembros (1/2)
public class SuperClase {public String str = "SuperClase.str";
void mostrar() {System.out.println("SuperClase.mostrar = " + str);
}}
public class SubClase extends SuperClase {public String str = "SubClase.str";
void mostrar() {System.out.println("SubClase.mostrar = " + str);
}
public static void main(String[] args) {SubClase sub = new SubClase();SuperClase sup = sub;sup.mostrar();sub.mostrar(); System.out.println("sup.str = " + sup.str);System.out.println("sub.str = " + sub.str);
} }
SubClase.mostrar = SubClase.strSubClase.mostrar = SubClase.strsup.str = SuperClase.strsub.str = SubClase.str
Resultado de Ejecución
Ejemplo de Redefinición de Miembros (2/2)
public class SuperClase {public String str = "SuperClase.str";
void mostrar() {System.out.println("SuperClase.mostrar = " + str);
}}
public class SubClase extends SuperClase {public String str = "SubClase.str";
void mostrar() {super.mostrar();System.out.println("SubClase.mostrar = " + str);
}public static void main(String[] args) {
SubClase sub = new SubClase();SuperClase sup = sub;sup.mostrar();sub.mostrar(); System.out.println("sup.str = " + sup.str);System.out.println("sub.str = " + sub.str);
} }
SuperClase.mostrar = SuperClase.strSubClase.mostrar = SubClase.strSuperClase.mostrar = SuperClase.strSubClase.mostrar = SubClase.strsup.str = SuperClase.strsub.str = SubClase.str
Resultado de Ejecución
Constructores en Clases Extendidas
l Al crear un objeto, el orden de ejecución es:l Se invoca el constructor de la superclase
(sino se especifica cual, se usa el por omisión)l Inicializar los campos usando sentencias de inicializaciónl Ejecutar el cuerpo del constructor
l Si se quiere usar un constructor específico de la superclase debe invocarse con super(...)
26
Ejemplo de Constructor (1/2)
public class superclase {protected int X = 1;protected int Y;
public superclase() {System.out.println("superclase: antes Y = " + Y);Y = X;System.out.println("superclase: después Y = " + Y);
}
public int getY() {return Y;
}}
Ejemplo de Constructor (2/2)public class subclase extends superclase {
private int Z = 3;public subclase() {
System.out.println("subclase antes: Y = " + Y);Y = Z;System.out.println("subclase despues : Y = " + Y);
} }
public class principal { public static void main(String[] args) {
System.out.println("Inicio de principal");subclase z = new subclase();System.out.println("Fin de principal");
}}
Inicio de principalsuperclase: antes Y = 0superclase: despues Y = 1subclase antes: Y = 1subclase despues: Y = 3Fin de principal
Resultado de Ejecución:
Modificador final
l Se puede usar en tres situaciones diferentes:l Variable . La variable no puede ser modificada
(constante)l Método. El método no puede ser redefinidol Clase. La clase no se puede derivar
(implícitamente todos sus métodos son finales)
l Uso de final en métodos y clases restringe reuso, por lo que debe usarse con reserva
La Clase Object
l Todas las clases tienen a Object como raíz, por lo tanto heredan sus métodos
l Existen dos tipos de métodos:l Métodos de utilidad generall Métodos para soportar hebras (threads)
l El último tipo no lo estudiaremos en el contexto de este curso
Object: Métodos de Utilidad General (1/2)
l public boolean equals(Object obj)l Compara si dos objetos tienen el mismo valorl Por omisión se supone que un objeto es sólo igual a si
mismol No es igual a verificar que tienen la misma referencia (se
puede hacer con ==)l public int hashCode()l Retorna código hashdel objeto, que es usualmente único
para cada objetol Sirve para ser usados en tablas de hash
Object: Métodos de Utilidad General (2/2)
l protected Object clone() throwsCloneNotSupportedException
l Retorna un clon del objeto (una copia de un nivel)l public final Class getClass()l Retorna un objeto de tipo Class que representa la clase
del objeto this. Permite utilizar reflexión.l public void finalize() throws Throwablel Finaliza un objeto durante la recolección de basura
l public String toString()l Retorna una representación del objeto en un Stringl Mayor parte de las clases lo redefinenl Utilizado por el operador ‘+’ entre strings y objetos
27
Métodos equals y hashCode
l Los métodos equals y hashCode deben ser redefinidos conjuntamente
l Normalmente dos objetos diferentes retornan diferentes códigos de hashl Para que dos objetos diferentes sean iguales en
valor deben retornar el mismo código de hash
Métodos equals y hashCodepublic class Persona {
private String rol;private String nombre;private String telefono;...public String getRol(){
return rol;}public String toString(){
return rol+": "+nombre;}public boolean equals(Object o){
if(!(o instanceof Persona))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
public class Igualdad {
public static void main(String[] args) {Integer Un = new Integer(1), otroUn = new Integer(1);
if (Un.equals(otroUn))System.out.println("objetos son iguales");
if(Un == otroUn)System.out.println("objetos son idénticos");
}
}
Clonación de Objetos
l El método clone permite clonar un objetol En principio, cambios posteriores en el clon no afectan al
estado del objeto original
l Una clase que permite clonar objetos normalmente implementa la interfaz Cloneable
l Aquellas clases que tienen variables miembros que son referencias deben redefinir el método clonel Agrega profundidad
Ejemplo de Clonación
public class Stack implements Cloneable {private Vector items;
// código de los métodos y constructor de Stack
protected Object clone() {try {
Stack s = (Stack) super.clone (); // clona el stacks.items = (Vector) items.clone(); // clona el vectorreturn s; // return the clone
} catch ( CloneNotSupportedException e) {// esto no debiera suceder dado que el Stack es clonablethrow new InternalError();
}}
}
Clases y Métodos Abstractos
l Permite definir clases que definen sólo parte de su implementaciónl Clases derivadas deben implementarlas
l Abstracción es útil cuando:l algún comportamiento es verdad para la mayoría de los
objetos de un tipo dado,l pero algún comportamiento sólo tiene sentido para
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
28
Ejemplo de Clase Abstractaabstract class ObjectoGrafico {
int x, y;. . .void mover(int nuevoX , int nuevoY) {
. . .}
abstract void dibujar();}
class Circulo extends ObjectoGrafico {void dibujar() {
. . .}
}
class Rectangulo extends ObjectoGrafico {void dibujar() {
. . .}
}
. . .ObjetoGrafico [] arreglo;. . .for(int i=0; i<arreglo.length;i++)
arreglo[i].dibujar();. . .
Cuándo y cómo extender Clases?
l Una clase que se extiende sigue siendo del tipo de la superclase (isA), no viceversal Ejemplo: Se se deriva pixel de punto, un pixel es un
punto, pero un punto no es un pixell A veces se extiende agregando nuevos
miembros (hasA)l Ejemplo: Un círculo tiene un punto, pero no es un
círculo.l En casos que la extensión permite tener
diferentes roles es más conveniente usar agregaciónl Ejemplo: Una persona que tiene roles diferentes no es
simple extenderla por derivación
Resumen
l Definición de Interfazl Herencia Múltiplel Supertipos y Subtipos
3.6 Interfaces y Paquetes
Interfaces, implementaciones, paquetes, organización de
archivos
3.6.1 Interfaces
Declaración, Herencia múltiple, supertipos y subtipos,
implementación
Introducción
l Mecanismo de Interfaz es una manera de declarar tipos consistentes sólo de métodos abstractos y constantes
l Clases deben implementar los métodos de las interfaces
l Las interfaces son útiles para el diseñol Clases deciden cómo implementarl Una interfaz puede tener muchas implementaciones
29
Interfaz vs. Clase Abstracta
l Interfaz es una simple lista de métodos abstractos (no implementados)
l Una interfaz se diferencia de una clase abstracta en:l Una interfaz no puede implementar ningún método, una
clase abstracta si lo puedel Una clase puede implementar varias interfaces, pero
puede tener una única superclasel Una interfaz no puede ser parte de una jerarquía de clasesl Clases no relacionadas pueden implementar una misma
interfaz
Ejemplo de Interfaz (1/2)
l Clase que puede monitorear variación de precios de las accionesl ObservadorAcciones es una interfaz de un observador
l Método cambioValor permite ser notificado de cambio preciol Un objeto de una clase que implementa esta interfaz se registra con
método observarAcciones para ser notificado de cambios
l accionMon permite definir la acción que interesa observar y delta la variación que ese considera interesante
public class MonitorAcciones {public void observarAcciones (ObservadorAcciones observador,
String accionMon, double delta) {...}
}
Ejemplo de Interfaz (2/2)
public interface ObservadorAcciones {final String enersisMon = ”Enersis";final String santaIsabelMon= ”Santa Isabel";final String copecMon = ”Copec";
void cambioValor(String accionMon, double nuevoValor);}
Constantes
Método
Declaración de la interfaz
Cuerpo de la Interfaz
Declaración de Interfaz
public interfaz <nombre interfaz> extends<lista de super-interfaces> {
<cuerpo de la interfaz>}
l public hace pública la interfaz fuera del paquete (opcional)
l La interfaz puede extender varias interfaces (opcional)
Cuerpo de la interfaz
l Todas las constantes son implícitamente:l públicas,l estáticas y l finales
l Todos los métodos son implícitamente:l públicos y l abstractos
l No se aceptan otros modificadores (e.g. private, protected y synchronized)
Implementación de una Interfaz
l Una interfaz define un conjunto de métodos.l Una referencia a una interfaz permite
suponer que los métodos existenl Una clase que “implementa” una interfaz se
compromete a “implementarlos”.l Definir código para cada uno de ellos.l Incumplimiento de contrato implica imposibilidad
de crear instanciasàclase abstractal Se deja la responsabilidad a los hijos.
30
Implementación de una Interfaz
public interface ObservadorEventos {
public void nuevoEvento(Date fecha, String evento);
}
public class Asistente implements ObservadorEventos {public void nuevoEvento(Date fecha, String evento){
System.out.println("Avisarle al jefe antes de las"+fecha+"!!"); }
}
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
public class Agenda {
private Vector observadores=new Vector();...
public void agregarObservador(ObservadorEventos o){observadores.add(o);
}
public void nuevoEvento(String evento){
for(int i=0;i<observadores.size();i++){ObservadorEventos oe = (ObservadorEventos) observadores.get(i);
oe.nuevoEvento(new Date(), evento);}
}}
Implementación de una Interfaz
public static void main(String args[]){
Agenda a = new Agenda();
Persona p = new Persona("NN", "112233");
Asistente asist = new Asistente();
a.agregarObservador(p );
a.agregarObservador(asist );
a.nuevoEvento ("reunion");
}
Ir a tomar la micro para la ‘reunion’!
Avisarle al jefe antes de las Mon Apr 05 17:08:49 VET 2004!!
Herencia Simple vs. Múltiplel Una clase puede extender exactamente una
superclasel Una interfaz puede extender múltiples interfacesl Herencia múltiple con clases puede producir
problemas debido a diferentes implementacionesl Ejemplo:l W tiene un campo wVarl Si Z hace referencia a wVar,
cuál es? Existen dos wVar?
l Java evita el problema permitiendo sólo herencia simple para clases
W
XY
Z
Extensión de interfaces
l Al igual que las clases, las interfaces pueden tener súper-interfaces.
l La interfaz hija “hereda” las definiciones de la interfaz padre.
l En este caso se permite herencia múltiple
Ejemplo de Interfaz Extendida (1/3)
public interface AdministradorRecursos {
public void agregarRecurso(String nombre, String driver);
public Collection recursosRegistrados ();
}
public interface AdministradorEntrada extends AdministradorRecursos{
public Collection recursosDirectos ();
public Collection recursosConBuffer();
}
public interface AdministradorSalida extends AdministradorRecursos {
public boolean bloquearRecurso(String recurso);
}
31
Ejemplo de Interfaz Extendida (2/3)
public interface AdministradorES
extends AdministradorEntrada, AdministradorSalida {
public void establecerBloqueos(int tipo);
}
Ejemplo de Interfaz Extendida (3/3)public class ControladorHDDs implements AdministradorES {
public void establecerBloqueos(int tipo) {...}
public Collection recursosDirectos() {...}
public Collection recursosConBuffer( ) {...}
public boolean bloquearRecurso(String recurso) {...}
public void agregarRecurso(String nombre, String driver) {...}
public Collection recursosRegistrados() {...}
}
public class PanelRemoto implements AdministradorES {
public void establecerBloqueos(int 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
l ¿Qué pasa si un mismo nombre se encuentra en más de una interfaz de los supertipos?l Si las firmas no son idénticas, es trivial (se sobrecargarán
diferentes métodos)l Si tienen firma idéntica, entonces la clase tendrá un solo
método con esa firmal Si las firmas sólo difieren en el tipo de retorno, no se
puede implementar la interfaz
l Para constantes es simple: se selecciona cada una usando nombre de la interfazl Ejemplo: X.var, Y.var
Modificación de Interfaces
l Una interfaz una vez declarada no debiera ser modificadal Ejemplo: Si se modifica la interfaz ObservadorAcciones
agregando un nuevo método, todas las clases que la implementan no son más válidas
l Por lo tanto, definición de una interfaz requiere diseño cuidadoso
l Problema anterior se soluciona definiendo una subinterfaz con el nuevo método
Interfaces comunes a implementar
l java.util.Iteratorl hasNext(), next(), remove()
l java.util.Collectionl add(), addAll(Collection c), clear(), contains (), ...
l java.lang.Comparablel compareTo(Object o)
l java.lang.Cloneablel Vacia!
l java.lang.Runnablel run()
l java.awt.event.ActionListenerl actionPerformed(ActionEvent e)
Ejemplo de Implementación de Interfaz (1/2)public class Proceso implements Comparable {
private static int lastPid=1;
private int pid;
private int priority;
public Proceso(){
pid=++lastPid ;
priority=0;
}
public int getPid (){return pid;}
public void nice( int p){priority+=p; }
public int compareTo(Object o ) {
if(!(o instanceof Proceso))
throw new ClassCastException();
return this.pid - ((Proceso) o).getPid();
}
}
32
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() {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 ());}
}}
3.6.2 Packages
Concepto de Paquete
l Contiene clases, interfaces y subpaquetesque están relacionados
l Razones para definirlos:l Permiten agrupar interfaces y clases relacionadasl Interfaces y clases pueden usar nombres públicos
populares sin tener conflictos con otros paquetesl Paquetes pueden tener componentes que sólo
están disponibles dentro del paquetel Facilita la distribución de software
Mecanismo de Definición
l En la primera línea de cada archivo fuente de una clase o interfaz debe aparecer:
package <nombre>l El nombre del paquete implícitamente se antepone
al nombre de la clase o interfazEjemplo: miPaquete.miClase
l Código externo al paquete puede referenciar a tipo internos del paquete de acuerdo a las reglas de control de acceso
Ejemplo de uso de Paquete
package personas
class Persona {private static int nextID = 0;private int ID;private String Nombre;private int edad = -1;
//... Otros métodos}
Se puede referenciar la clase Persona por:personas.Persona
Referencias Externas
l Una forma es anteponer el nombre del paquete a cada tipo (si existen subpaquetes se puede definir una jerarquía)l Esta forma es razonable si se usan pocas referencias a
tipos del paquetel La otra forma es mediante import , lo que permite
usar referencias en el código sin anteponer nombre del paquetel Ejemplo
import Personas.*// ahora se puede usar la clase Personas sin// anteponer nombre del paquete
33
Colisiones de Nombre entre Paquetes
l Si se usa más de un paquete se pueden producir colisiones de nombre.
l Para controlar el uso correcto se puede usar:l 1. Anteponer el nombre del paquete en aquellos casos de
colisión (e.g. Personas.Persona)l 2. Importar en forma completa un solo paquete y usar nombres
completos para los nombres que colisionanl Caso real
l java.util.Date y java.sql.Date
l Ejemplo:import Personas.*// OtrasPersonas.Persona se refiere al otro paquete// Persona se refiere ahora a Personas.Persona
Colisiones de Nombres de Paquetes
l Si dos paquetes tienen el mismo nombre y requieren ser usados existe un problema
l Una solución es usar nombres anidadosl Ejemplo: miproyecto.mipaquete.*
l En grandes organizaciones se acostumbra a usar nombres de dominio de Internet en orden inversol Ejemplo: cl.utfsm.siga.mipaquete.*
Control de Acceso a Paquetes
l Clases e Interfaces tienen dos accesos:l Público. Si se califican con public esta permitido su
acceso fuera del paquetel Paquete. Sino se declara public, su acceso se restringe
dentro del paquetel Miembros de clase declarados:l Sin modificador de acceso son accesibles dentro del
paquete, pero fuera de éll Miembros no privados son accesibles por cualquier código
del paquete (son amistosos)
Recomendaciones
l Paquetes se deben definir para clases e interfaces relacionadasl Tal agrupación permite una mejor reutilizaciónl Permite usar nombres adecuados sin provocar colisiones
l Los paquetes se pueden anidarl Permite agrupar paquetes relacionados (e.g. java.lang)l Es un asunto organizacional, no de control de accesol Jerarquía típicamente se refleja en la estructura del
directorio
Paquetes y directorios
l Los nombres de paquetes condicionan el lugar donde buscar las clases
l La jerarquía de paquetes debe ser idéntica a la jerarquía de directorios
Paquetes y directoriospackage usm.lp.agenda;public class Agenda {...
}
~home/usm/
lp/agenda/
Agenda.javaPersona.java....
34
Paquetes de Java
l java.langl java.iol java.utill java.mathl java.awtl java.net
• java.rmi• java.applet• java.sql• java.beans• java.security• etc.
Extensiones a Java
l javax.swingl javax.servletl javax.cryptol javax.accessibilityl javax.namingl javax.transactionl javax.xmll javax.soundl javax.printl etc.
Resumen
l Definición de Interfazl Herencia Múltiplel Conflictos de Nombresl Supertipos y Subtiposl Implementación de Interfacesl Paquetesl Control de Componentes de Programas
3.7 Caracteres, String y Otros Tipos de
Datos
Arreglos, Character, String, StringBuffer, Number, Date
3.7.1 Arreglos
Arreglos en Java
l Arreglos en Java son agrupaciones ordenadas de 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 variablesl La dimensión se determina en la creación del arreglol Tamaño permanece fijo después de su creación
l Los índice varían desde 0 a largo-1l Acceso ilegal lanza IndexOutOfBoundsException
l Los arreglos no se pueden derivar
35
Ejemplo de un Arreglo
public class demoArreglo {public static void main(String[] args) {
// declarar un arreglo de enterosint[] unArreglo;// crear un arreglo de enterosunArreglo = new int[10];// asigna un valor a cada elemento del arreglo e imprimefor ( int i = 0; i < unArreglo.length ; i++) {
anArray[i ] = i;System.out.print(unArreglo[i] + " ") ;
}System.out.println();
}}
Uso de Arreglos
l Declaración de un Arreglo (sin tamaño)l tipo[] variable;
l Creación de un arreglo vacío (especifica tamaño)l variable = new tipo[tamaño];
l Creación e inicialización rápidal tipo[] variable = {val0, val1, ... , valn-1};
l Acceso a un elemento del arreglol variable[indice]
l Tamaño del arreglol variable.length
Arreglo de Arreglospublic class ArregloDeArreglo {
public static void main(String[] args) {String[][] cartoons = {{"Flintstones ","Fred" ,"Wilma" ,"Pebbles", "Dino" } ,{"Rubbles ","Barney"," Betty"," Bam Bam " },{"Jetsons ","George","Jane","Elroy "," Judy ","Rosie ","Astro" },{"Scooby Doo Gang ","Scooby Doo"," Shaggy" ,"Velma" ,"Fred", "Daphne" }};for ( int i = 0; i < cartoons.length; i++ ) {
System.out.print(cartoons[i][0] + ": ");for ( int j = 1; j < cartoons[i].length; j++)
System.out.print(cartoons[i][j] + " ");System.out.println();
}}}
Flintstones: Fred Wilma Pebbles DinoRubbles: Barney Betty Bam BamJetsons: George Jane Elroy Judy Rosie Astro Scooby Doo Gang: Scooby Doo Shaggy Velma Fred Daphne
Copiado de Arreglos
l Para copiar un arreglo se puede usar método arraycopy de System:l public static void arraycopy(
Object fuente,int indiceFuente,Object destino,int indiceDestino,int largo)
Ejemplo de Copia de Arreglos
public class DemoCopiaArreglos {public static void main(String[] args) {
char[] copiarDesde = { 'd', 'e', 'c', 'a', 'f', 'e', 'i', 'n', 'a', 't', 'e', 'd' };char[] copiarA = new char[7];
System.arraycopy(copiarDesde, 2, copiarA, 0, 7);System.out.println(new String(copiarA));
}}
cafeina
Utilidades para arreglos
l Clase utilitaria java.util.Arraysl static int binarySearch(<tipo>[] a, <tipo> key)l static boolean equals(<tipo>[] a, <tipo>[] a2) l static void fill(<tipo>[] a, <tipo> val)l static void sort(Object[] a)l Los objetos deben implementar la interfaz java.util.Comparable
36
3.7.2 Caracteres y Strings
Clases Básicas para Caracteres
l Character.Clases cuyas instancias pueden 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 Characterl Character(char )
l Constructor crea objeto inmutablel int compareTo(Character )
l Retorna entero que compara con otro carácterl boolean equals(Object)
l Retorna true si son de igual valorl String toString()
l Convierte a stringl char charValue()
l Retorna valor del objetol isUpperCase(char )
l Retorna true si es mayúscula
Ejemplo de Characterpublic class CharacterDemo {
public staticvoid main(String args[]) { Character a = new Character('a');Character a2 = new Character('a');Character b = new Character('b');int diferencia = a.compareTo(b);
if (difference == 0) {System.out.println("a es igual a b.");
} else if (diferencia < 0) { System.out.println("a es menor que b.");
} else if (diferencia > 0) { System.out.println("a es mayor que b.");
}System.out.println("a es " + (( a.equals(a2)) ? “igual" : “no igual") + " a a2.");System.out.println(“El carácter " + a.toString() + " es " +
(Character.isUpperCase(a.charValue()) ? “mayúscula" : “minúscula"));}
}
Ejemplo de String y StringBuffer
public class StringsDemo {public static void main(String[] args) {
String palindrome = “ recocer ";int largo = palindrome.length();StringBuffer destino = new StringBuffer(len);for (int i = (largo - 1); i >= 0; i--) {
destino.append(palindrome.charAt(i));}System.out.println(destino.toString());
}}
Creación de Strings y StringBuffers
l Java permite crear un String en diversas situacionesl Ejemplo:
“Este es un String" // literal
String palindrome = “recocer"; // referencia String
char[] ArregloHola = { 'h', ‘o', 'l', ‘a'}; // arreglo de caracteres
String StringHola = new String(ArregloHola);
System.out.println(StringHola);
n StringBuffer debe siempre usar new para crear un string
37
Métodos Accesores(Comunes)
l int length()l Obtiene el largo del String o StringBuffer
l char charAt(int pos) l Obtiene carácter en posición pos. 0 es el primero y
length()-1 el últimol String substring(int), String substring(int, int)l Obtiene parte del Stringl Los dos enteros indican primera y última posición. Sino se
indica segundo entero, se asume hasta el final
l String toString()l Convierte a string
Métodos Específicos de String
l indexOf(int caracter),lastIndexOf(int caracter) l Retorna índice de la primera (última) ocurrencia de caracter
l indexOf(int car, int desde),lastIndexOf(int car, int desde)l Retorna índice de primera (última) ocurrencia de carácter,
buscando hacia delante (atrás) desde índice especificadol indexOf(String str),
lastIndexOf(String str)l Retorna índice de la primera (última) ocurrencia del String str.
l indexOf(String str, int desde),lastIndexOf(String str, int from)l Retorna índice de primera (última) ocurrencia de String str ,
buscando hacia delante (atrás) desde índice especificado.
Métodos Específicos de Stringl int compareTo(String otroString)l Compara dos lexicográficamente(interfaz Comparable)
l String concat(String str)l Concatena el stringstr al final
l String toLowerCase() l Convierte un String a minúsculas
l String toUpperCase() l Convierte un String a mayúsculas
l etc.l VER:
http://java.sun.com/j2se/1.4/docs/api/java/lang /String.html
Métodos de StringBuffer
l StringBuffer append(String str)l Agrega str al final del buffer de string.
l int capacity()l Retorna la capacidad actual del buffer de string
l StringBuffer insert(int offset, String str)l Inserta str en la posición offset del buffer de string.
l StringBuffer delete (int inicio, int fin)l Elimina los caracteres entre inicio y fin
l etc.l VER:
http://java.sun.com/j2se/1.4/docs/api/java/lang /StringBuffer.html
3.7.3 Números
Wrappers y funciones
Clase Numberl byte byteValue()l Retorna el valor del número especificado como byte
l double doubleValue()l Retorna el valor del número especificado como double
l float floatValue()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
38
Clases Extendidas de Numberl Byte. Clase envolvente para bytel Double. Clase envolvente para doublel Float. Clase envolvente para floatl Integer. Clase envolvente para intl Long. Clase envolvente para longl Short. Clase envolvente para shortl BigDecimal. Número decimal de precisión arbitrarial BigInteger. Número entero de precisión arbitraria
Funciones Matemáticas
l El paquete java.lang.Math contiene funciones tales como:l exponenciaciónl logaritmosl raíz cuadradal Funciones trigonométricasl Máximos y mínimosl Redondeosl etc.
l Verl 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
l Al desplegar los valores con toString se debieran hacer en el formato de la localidadl Inglés: 123456.78l Francés: 123 456,78l Alemán: 123.456,78
l Java provee soporte para realizar tales conversiones en paquete java.textl NumberFormatl DecimalFormat
3.7.4 Date
Fecha y hora
Clase java.util.Date
l Útil para manejar datos fecha/horal Constructor por defecto entrega fecha actuall Operacionesl Comparaciónl Sumal Formato
l Clase utilitariasl java.util.Calendarl java.text.DateFormat
3.8 Manejo de Excepciones
Excepciones, clasificación, lanzamiento y manejadores de
excepciones
39
Motivación
l Cuando ocurren errores es importante que un programa sea capaz de reaccionar al evento (capturarlo)
l Ejemplo de acciones posibles:l Notificar al usuario de un errorl Guardar el trabajo hechol Volver a un estado seguro anteriorl Terminar limpiamente el programa
l Ejemplos de errores:l Error en la entrada de datosl Error en un dispositivo (e.g. Impresora apagada, disco lleno)l Error en el código
Concepto de Excepciones
l Una excepción corresponde a un evento que interrumpe el flujo normal de ejecución
l Cuando ocurre tal tipo de evento en un método, se lanza (throw) una excepción, creando un objeto especial que se pasa al runtime para manejar la excepción
l El runtime busca en el stack el método que maneje el tipo de excepciónl Si se encuentra se captura la excepción invocando al
manejador de la excepción (catch) l Si no se encuentra se termina el programa
Ventajas de Excepciones
l Separa el código de manejo de errores del código normall Hace más legibles los programas
l Propaga errores a través de los métodos que se encuentran activos en el stackl Transfiere el control en el anidamiento de invocaciones al
lugar adecuado para su manejo
l Permite agrupar errores y diferenciar erroresl Una excepción es una clase que se puede derivar
Excepciones:Comparación con Java (1/2)
TipoError leerArchivo(char * mi Archivo) {int errorCode = 0;int fd;int n;if ((fd = open(“ miArchivo ”) < 0))
return ERROR_ABRIR_ARCHIVO;int n = largo del archivo;if (n < 0) {
close(fd);return ERROR_LARGO_ARCHIVO;
}while ((n = read(fd,...)) > 0)
procesar();if (n != EOF)
return ERROR_LECTURA_ARCHIVO;}
Excepciones:Comparacióncon Java (2/2)
class ejemplo {
public void leerArchivo() throws IOException {try {
File arch = new File("miArchivo");FileReader in = new FileReader(arch);int c;while ((c = in.read()) != -1)
procesar(c);in.close();
} catch (IOException) {hacer algo;
}}
}
Ejemplo: Anidamiento de Excepciones
método1 {try {
call método2;} catch (exception) {
procesar excepción;}
}
método2 throws exception {call método3;
}
método3 throws exception {call leerArchivo ;
}1
2
3
4
5
40
Jerarquía de Clases de Excepciones
l En Java toda excepción se deriva de la clase Throwable
l Existen dos subclase:l Error. Representa un error interno irrecuperable o
agotamiento de recursos en el sistema de runtime de Javal 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)
Jerarquía de Excepciones
ThrowableThrowable
ErrorError ExceptionException
IOExceptionIOException RuntimeExceptionRuntimeException....
Subclases de Exceptionl RuntimeException se debe a un error de programación
l mal uso de castl Acceso a arreglo fuera de límitel Acceso con puntero nulo
l IOException son por algún otro problema:l Leer más allá del final del archivol Abrir una URL mal formadal etc.
Tipos de Excepciones
l Excepciones no verificadas (unchecked)l Excepciones derivadas de la clase Error y
RuntimeExceptionl OutOfMemoryErrorl StackOverflowErrorl IndexOutOfBoundsException, l ClassCastExceptionl NullPointerExceptionl ...
l Excepciones verificadas (checked)l Otras clases de excepciones
l IOException, l ClassNotFoundExceptionl SQLExceptionl ...
Métodos: Manejo de Excepcionesl Un método advierte al compilador sobre excepciones que no
puede manejar lanzándola con throwsl Ejemplo:
public String leerLinea() throws IOExceptionl Un método debe declarar todas las excepciones verificadas
(checked)l Si no declara todas, el compilador reclamal Al declarar una clase de excepciones, entonces puede lanzar
cualquier excepción de alguna subclasel Aquellas excepciones que son capturadas (catch) no salen del
método y no debieran ser declaradas
Cómo lanzar una excepción?
l Los pasos son:l Se debe elegir una clase apropiada de excepciónl Crear un objeto de excepción de esa clasel Lanzar la excepción con throw
l Ejemplo:
throw new ClaseExcepción();
if (ch == -1) { // se encuentra EOFif (leidos < tamaño)
throw new EOFException();}
41
Ejemplo: Lanzamiento de Excepción
public Object pop() throws EmptyStackException{Object obj;
if (size == 0)throw new EmptyStackException();
obj = objectAt(size - 1);setObjectAt(size - 1, null);size--;return obj;
}
Creación de Clases de Excepcionesl Si las excepciones estándares no son adecuadas, el
usuario puede definir las propias, derivando alguna clase existente
l Es práctica común definir un constructor de omisión y otro con un mensaje detallado
l Ejemplo:
class FileFormatException extends IOException {public FileFormatException() {}
public FileFormatException(String msg) {super(msg);
}}
Ejemplo de uso de Excepción
public String leer(BufferLectura lector)throws FileFormatException {...while (...) {
if (ch == -1) { // se encuentra EOFif (leidos < tamaño)
throw new FileFormatException();}...return str;
}
Capturando Excepciones
l Sentencia try permite definir un bloque de sentencias para las cuales se quiere definir un manejador de excepciones
l Para cada clase de excepción se define un manejador diferente con catchl Usando una superclase común varias subclases diferentes de
excepciones pueden tener un único manejadorl Forma:
try {// grupo de sentencias
} catch (ClaseExcepción1 e) { ...}
} catch (ClaseExcepciónn e) { ...}
Ejemplo: Manejadores de Excepciones
try {. . .
} catch (ArrayIndexOutOfBoundsException e) {System.err.println ("Agarró ArrayIndexOutOfBoundsException : " +e.getMessage());
} catch (IOException e) {System.err.println ("Agarró IOException: " +e.getMessage());
}
Relanzando una Excepción
Graphics g = imagen.getGraphics();try {
// código que lanza excepciones} catch (MalformedURLException e) {
g.dispose();throw e;
}
Relanza la excepción capturada por el manejador de MalformedURLException
¡Se podría lanzar también una excepción diferente!
42
Cláusula finally
l Cuando se lanza una excepción se detiene el procesamiento normal del métodol Esta situación puede ser un problema si el método ha
adquirido recursosl Se hace necesario disponer de un código de limpieza
l La solución es usar la cláusula finally, que se ejecuta haya o no excepción antes de retornarl En caso de capturar una excepción, el código de manejo
se ejecuta antes que el de finallyl Finally se ejecuta siempre, incluso si se alcanza un return
en condiciones normales.
Ejemplo de finallypublic void writeList() {
PrintWriter out = null;try {
System.out.println("Entering try statement") ;out = new PrintWriter(new FileWriter ("OutFile.txt"));if (size < 0)
return;for ( int i = 0; i < size; i++ )
out.println(" Value at : " + i + " = "+ victor.elementAt(i));
} catch ( ArrayIndexOutOfBoundsException e) {System.err.println("Caught ArrayIndexOutOfBoundsException: "
+ e.getMessage());} catch ( IOException e) {
System.err.println("Caught IOException: " + e.getMessage ());} finally {
if (out ! = null) {System.out.println("Closing PrintWriter" );out.close ();
} elseSystem.out.println("PrintWriter not open ");
}}
Resumen
l El mecanismo de excepciones permite transferir el control cuando suceden errores en el programa
l El código de manejo de los errores se puede separar del código de desarrollo normal
l Cada método debe declarar las excepciones verificadas (checked) que no puede manejar, de manera que los programadores sepan al usar la clase que excepciones pueden esperar
3.9 Streams y Archivos
Streams, clases, archivos, streams de objetos y
serialización
3.9.1 Streams Básicos
Streams de Bytes y Caracteres
l E/S es en principio una secuencia de bytesl Ejemplo: Archivo, dispositivo, conexión red, etc.
l Java provee dos clases básicas para bytes:l InputStream : Secuencia de bytes de entradal 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 Unicodel Writer : Salida de caracteres Unicode
l De estas cuatro clases abstractas Java deriva las demás clases
43
API de InputStream (1/2)
l abstract int read()l Lee un bytede entrada (retorna -1 se llega al final)
l int read(byte[] b)l Lee un arreglo de bytes (lee a lo más b.length bytes)l Retorna bytes leídos (retorna -1 si está al final)
l int read(byte[] b, int off, int largo)l Lee un arreglo de bytes (lee a lo más b.length bytes)l Retorna bytes leídos (retorna -1 si está al final)l off: offset en arreglo bl largo: Máximo # de bytes a leer
API de InputStream (2/2)l long skip(long n)l Salta n bytes en la entrada (retorna # de bytes saltados)
l int avalaible()l Retorna # de bytes disponibles sin bloquear
l void close()l Cierra entrada
l void mark(int lim)l Coloca marca en posición actual. Se borra al leer lim bytes
l void reset()l Vuelve a posición de última marca
l boolean markSupported()l retorna verdadero si soporta marcas
API de OutputStreaml abstract void write(int n)l Escribe un byte de datos
l void write(byte[] b)l Escribe todos los bytes en el arreglo b
l void write(byte[] b, int off, int largo)l Escribe largo bytes desde posición off en el arreglo b
l void close()l Cierra la salida
l void flush()l Vacía la salida (escribe datos mantenidos en buffer)
API de Reader y Writer
l Readerl int read()l int read(char cbuf[])l int read(char cbuf[], int offset, int largo)
l Writerl int write(int c)l int write(char cbuf[])l int write(char cbuf[], int offset, int largo)
Conjunto de Streams
l Java provee más de 60 clases de streamsl Todas las clases se derivan de las 4 clases
básicasl Clases básicas sólo permiten leer o escribir
bytes o caracteres
Subclases de Reader y Writer
44
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 archivol 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);
double d = din.realDouble();
PushbackInputStream pbin = new PushbackInputStream(new BufferedInputStream
(new FileInputStream(“miArchivo.txt”)));...int b = pbin.read();if (b != “<“)
pbin..unread(b);
3.9.2 Archivos
Clases Básicas de Archivos
l FileReader. Lectura de caracteresl FileWriter. Escritura de caracteresl FileInputStream . Lectura de bytesl FileOutputStream . Escritura de bytes
Constructores para Archivos
l Las cuatro clases anteriores aceptan tres tipos de constructoresl FileInputStream in = new
FileInputStream (“miArchivo”);
l File f = new File(“miArchivo”)FileInputStream in = new FileInputStream(f);
l FileDescriptorfd = ...;FileInputStream in = new FileInputStream(fd);
45
FileInputStream in = newFileInputStream(archivoEntrada);
FileOutputStream out = newFileOutputStream(archivoSalida);
Ejemplo: Copia de Archivoimport java.io.*;
public class Copy {public staticvoid main(String[] args) throws IOException {
File archivoEntrada = new File(”Entrada.txt");File archivoSalida = new File(”Salida.txt");
FileReader in = new FileReader(archivoEntrada);FileWriter out = new FileWriter(archivoSalida);
int c;while ((c = in.read()) != -1)
out.write(c);
in.close(); out.close();}
}
Clase File
l No corresponde a un stream (se deriva de Object), que permite tener repesentaciónabstracta de archivos y directorios
l Está definida en paquete java.iol Posee métodos tales como:l Crear directorio, renombrar, borrar, sendero del
archivo, listar directorio, etc.
Clase RandomAccessFile
l intskipBytes(int)l Mueve el puntero el # de bytes indicado hacia
adelante
l void seek(long)l Posiciona el puntero justo antes del byte
especificado
l long getFilePointer()l Retorna la posición actual del puntero
Streams y Archivos ZIP
l Se usan para archivar uno o más archivos en formato comprimido (GZIP o ZIP)
l Cada archivo tiene un cabecera con información tal como:l Nombre del archivo, método de compresiónl Para procesar una entrada se deben leer las entradas
l Java provee cuatro clases para compresión definidas en paquete java.util.zip.* :l ZipInputStream. Stream de entrada comprimidal ZipOutputStream . Stream de salida comprimidal ZipEntry. Describe una entradal ZipFile. Archivo ZIP
3.9.3 StreamsEspeciales
Streams de Buffering
l BufferedInputStreaml Permite usar buffer de entrada para leer sin
causar un acceso a dispositivo en cada operación
l BufferedOutputStreaml Idem para salida
l PushbackInputStreaml Permite devolver datos al stream
46
Clases DataInput y DataOutputl boolean
readBoolean()l byte readByte()l char readChar()l double readDouble()l float readFloat()l int readInt()l String readLine()l long readLong()l short readShort ()
void writeBolean(boolean b)void writeByte(byte b)void writeChar(char c)void writeChars(String s)void writeDouble (double d)void writeFloat(float f)void writeInt(int i)void writeLong (long l)writeShort(short s)
¡Leen y escriben en binario!
Clase PrintWriter
l Permite escribir texto formateado(no se especifica destinatario)l void print(Object)l void print(String s)l void println(Strings)l void print(char[] s)l void print(char c)l void print(int i)l etc.
¡Java no provee un stream similar para entrada formateada!
Ejemplo de PrintWriter
PrintWriter out = new PrintWriter (new FileOutputStream (“miArchivo”));
...out.print(“Esta es una prueba ”);out.print(2002);... Especifica
destinatario
Java no provee un stream similar para entrada formateada
System.in y System.out
l System.out es un PrintStreaml System.out.println(“....”);
l System.in es un InputStreaml ¿Cómo leer desde el teclado?java.io.BufferedReader br;
try{
br = new java.io.BufferedReader(
new java.io.InputStreamReader(System.in));
String str = br.readLine();
System.out.println("Ud ingreso "+str);
}catch(java.io.IOException ioe){
}
Resumen
l Los streams son el mecanismo básico de Java para proveer E/S y son parte de java.io
l Streams se pueden componer para lograr el servicio deseado
l Existen herramientas en java.util para apoyar en el uso de streams
3.10 Diseño de programas OO
Patrones de diseño
47
Patrones de diseño
l Son formas convenientes de reutilizar código orientado a objetos entre proyectos y programadores
l Promueven que los objetos se ocupen solo de “sus propios asuntos”.
l Un patrón aborda un problema de diseño recurrente que aparece en situaciones especificas y que represente una solución a este.
Factory
l Una “fábrica” es un patrón que devuelve una instancia de una clase entre un conjunto de posibilidades dependiendo de la información proveída.
l Generalmente devuelve una clase abstracta o una interfaz.
l El programador no sabe que instancia específica esta usando.
1º Ejemplo de Factory (1/4)
l Clase para separar un nombre en dos partes.l Clase base con dos hijas.
abstract class Namer{
protected String first;
protected String last;
public String getFirst() {
return first;
}
public String getLast() {
return last;
}
}
1º Ejemplo de Factory (2/4)class FirstFirst extends Namer{
public FirstFirst(String s) {
int i = s.lastIndexOf(" " );
i f (i > 0 ) {
first=s.substring(0, i).trim();
last=s.substring(i + 1).trim();
} else {
first = " ";
last = s;
}
}
}
class LastFirst extends Namer{
public LastFirst(String s) {
int i = s.indexOf("," );
i f (i > 0 ) {
last=s.substring(0,i).trim();
first=s.substring(i+1).trim();
} else {
last = s;
first = " ";
}
}
}
1º Ejemplo de Factory (3/4)
public class NameFactory {
public Namer getNamer(String entry) {
int i = entry.indexOf(",");
if (i > 0)
return new LastFirst(entry);
else
return new FirstFirst(entry);
}
}
1º Ejemplo de Factory (4/4)public static void main(String[] args) {
NameFactory factory = new NameFactory();
Namer namer ;
namer = factory.getNamer("Perez, Juanito") ;
System.out.println( "First: " + namer.getFirst());
System.out.println( "Last: " + namer.getLast());
namer = factory.getNamer("Maria Espinoza") ;
System.out.println( "First: " + namer.getFirst());
System.out.println( "Last: " + namer.getLast());
}
First: Juanito
Last: Perez
First: Maria
Last: Espinoza
48
2º Ejemplo de Factory (1/4)
l Fabrica de objetos para realizar logginl Utilización de configuraciones por defecto
interface Logger{public void doLog(String message, int level);
}abstract class AsbtractLogger implements Logger{
private int minLevel;protected AsbtractLogger(int level){
minLevel=level;}
public void doLog(String message, int level){if(level>=minLevel)
doLog(message);}abstract protected void doLog(String message);
}
2º Ejemplo de Factory (2/4)class NetLogger extends AsbtractLogger{
public NetLogger(URL destiny, int minLevel){
super (minLevel);
}
protected void doLog(String message) {
System.out.println("[NetLogging]" +message);
}
}
class FileLogger extends AsbtractLogger{
public FileLogger(File destiny, int minLevel){
super (minLevel);
}
protected void doLog(String message) {
System.out.println("[FileLogging]"+message);
}
}
2º Ejemplo de Factory (3/4)public class LoggerFactory {
private int defaultLevel=0;private String defaultDestiny;
public void setDefaultLevel(int l){defaultLevel=l;}public void setDefaultDestiny(String str) {defaultDestiny = str;}
public Logger createLogger(){return createLogger(defaultDestiny);}public Logger createLogger(String destiny){
try{URL url = new URL(destiny);return new NetLogger(url, defaultLevel);
}catch(MalformedURLException mue){}try{
File file = new File(destiny);if(file.exists())
return new FileLogger(file,defaultLevel);else
throw new FileNotFoundException();}catch(FileNotFoundException fnfe){}
return null;}
}
2º Ejemplo de Factory (3/4)public static void main(String[] args) {
LoggerFactory factory = new LoggerFactory();
factory.setDefaultLevel(2);
factory.setDefaultDestiny("http://log.inf.utfsm.cl") ;
Logger logger1= factory.createLogger();
logger1.doLog("test1" , 1);
logger1.doLog("test2" , 2);
logger1.doLog("test3" , 3);
logger1.doLog("test4" , 4);
Logger logger2 = factory.createLogger("test.log" );
logger2.doLog("test1" , 1);
logger2.doLog("test2" , 2);
logger2.doLog("test3" , 3);
logger2.doLog("test4" , 4);
}
[NetLogging]test2
[NetLogging]test3[NetLogging]test4[FileLogging]test2
[FileLogging]test3[FileLogging]test4
Singleton
l Un “singleton” es un objeto que requiere tener una sola instancia creada de manera simultanea.
l Útil para mejorar rendimiento y asegurar recursos no compartidos.
1º Ejemplo de Singleton (1/3)
l Spooler de impresión.l Solo se permite un numero máximo de
instancias.
49
1º Ejemplo de Singleton (2/3)public class PrintSpooler {
private static int instances=0;
private static int maxInstances=2;
private PrintSpooler(){}
public static PrintSpooler newSpooler(){
if(instances>=maxInstances)
return null;
else{
instances++;
return new PrintSpooler();
}
}
public void finalize(){
instances --;
}
}
1º Ejemplo de Singleton (3/3)public static void main(String[] args) {
PrintSpooler ps1,ps2, ps3;
ps1 = PrintSpooler.newSpooler();
if(ps1!=null) System.out.println( "First spooler created" );
else System.out.println("First spooler not created!" );
ps2 = PrintSpooler.newSpooler();
if(ps2!=null) System.out.println( "Second spooler created");
else System.out.println("Second spooler not created" );
ps3 = PrintSpooler.newSpooler();
if(ps3!=null) System.out.println( "Third spooler created" );
else System.out.println("Third spooler not created") ;
}
2º Ejemplo de Singleton (1/3)
l Conexión a la base de datosl Una sola instancial Se puede mezclar con una fabrica
2º Ejemplo de Singleton (2/3)public class DBConnection {
private static DBConnection instance=null;
private static String defaultSetup;
private String setup;
private DBConnection(String s){setup=s;}
public static void setParameters(String str){defaultSetup=str;};
public static DBConnection getConnection(){
if(instance== null )
instance = new DBConnection(defaultSetup);
return instance;
}
public void finalize(){
instance= null ;
}
}
2º Ejemplo de Singleton (3/3)
public static void main(String[] args) {
DBConnection dbc1, dbc2;
DBConnection.setParameters("jdbc:oracle:thin:bd.inf.utfsm.cl/db1");
dbc1 = DBConnection.getConnection();
dbc2 = DBConnection.getConnection();
if(dbc1==dbc2)
System.out.println("Only one connection" );
else
System.out.println("More than one connection");
}
Patrones de diseño empresariales
l Principalmente para aplicaciones distribuidas.
l Incluyen conceptos de J2EE.l Mantienen complejidad baja y alta
mantenibilidad en sistemas web integrados con un back-end.
50
View Helper
l Motivaciónl 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ónl Una vista (View) contiene el código de formato,
delegando las responsabilidades de procesamiento a una clase que la asiste (Helper).
View Helper
View Helper Session Facadel 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 complejidadde 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 hacia los servicios, permitiendo un mal uso de las interfaces de los componentes.
l Soluciónl 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 estrategia de acceso uniforme de menor granularidad.
Session Facade Session Facade
51
Data Access Object
l Motivaciónl Las aplicaciones requieren de datos persistentesl 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ónl 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
Data Access Object Ejemplo completo
l DAO para recuperar productos e usuariosl XMLl Base de datosl Web service
l Componentes del negocio para listar y vender productos
l Fachada para encapsular funcionalidadl Cliente que accede a los servicios
DAO para usuarios
public class User {
private int rut;
private String nombre;
public User(String n){setNombre(n);}
public int getPK(){return rut;}
public void setNombre(String n){nombre=n;}
}
DAO para usuariosclass UserDAO {
private User user ;
public UserDAO(User u){user = u;}
public boolean load() throws SQLException{
int rut = this.user.getPK ();
user.setNombre("pedrito") ;
return false;
}
public boolean store() throws SQLException{
int rut = this.user.getPK ();
return false;
}
public static Collection getUsers (){
return null;
}
}
52
DAO para usuariospublic static void main(String args[]){
User u =new User("111111");
UserDAO dao = new UserDAO(u);
try{
dao.load();
u.setNombre("Juanito");
dao.store();
}catch(SQLException sqle){}
}
DAO para productospublic class Product {
private String code;
public String getCode(){
return code;
}
}
abstract class ProductDAO{
public abstract Product[] getProducts();
public abstract Product[] getFilteredProducts(String str);
public abstract int getStock(Product p);
public abstract void decrementStock(Product p);
}
class ProductXMLDAO extends ProductDAO{
public Product[] getProducts( ) {return null; }
public Product[] getFilteredProducts(String string) {return null ;}
public int getStock(Product p ) {return 0;}
public void decrementStock(Product p ) {}
}
class ProductDBDAO extends ProductDAO{
public Product[] getProducts( ) {return null; }
public Product[] getFilteredProducts(String string) {return null ;}
public int getStock(Product p ) {return 0;}
public void decrementStock(Product p ) {}
}
class ProductWSDAO extends ProductDAO{
public Product[] getProducts( ) {return null; }
public Product[] getFilteredProducts(String string) {return null ;}
public int getStock(Product p ) {return 0;}
public void decrementStock(Product p ) {}
}
DAO para productosDAO para productos
class ProductDAOFactory{
private static String source= "jdbc:postgresql:localhost:5432/myDb";
private static ProductDAO instance=null;
public static ProductDAO createProductDAO(){
if(instance!= null ) return instance;
if(source.equals( "source.xml" ))
instance = new ProductXMLDAO();
else if(source.equals ("jdbc:postgresql:localhost :5432/myDb") )
instance = new ProductDBDAO();
else if(source.equals ("http://localhost:8081/ws" ))
instance = new ProductWSDAO();
return instance;
}
}
Singleton
Factory
Componentes del negocio
l Un componente para agrupar tareas de recuperación de información.
l Un componente para agrupar tareas de modificación de información.
class ProductRetriever{
ProductDAO pDao = null;
public ProductRetriever(){
pDao = ProductDAOFactory.createProductDAO();
}
public Product getProduct(String code){
Product[] arr= pDao.getFilteredProducts( "code="+code );
if(arr.length >0) return arr[0];
else
throw new IllegalArgumentException
("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());
...
}
}
Componentes del negocio
53
Componentes del negocio
class ProductManager{
ProductDAO pDao = null;
public ProductManager(){
pDao = ProductDAOFactory.createProductDAO();
}
public boolean dispatchProduct(Product p, User u){
if(pDao.getStock(p)>0)
pDao.decrementStock(p);
...
}
}
public class ProductFacade {
private ProductRetriever retriever=new ProductRetriever();
private ProductManager manager = new ProductManager();
private User loggedUser;
public ProductBean listProducts(){
...
}
public boolean sellProduct(String pCode, int quantity){
...
}
public static class ProductBean{
...
}
}
Fachada de listado y venta
Fachada de listado y venta:Listado
public ProductBean listProducts(){
ProductBean bean = new ProductBean();
bean.setProducts(retriever.getProducts());
bean.setUserProducts(retriever.getUserProducts(loggedUser ));
return bean;
}
Fachada de listado y venta:Venta
public boolean sellProduct(String pCode, int quantity){
Product p;
try{
p=retriever.getProduct(pCode);
}catch(IllegalArgumentException iae){
return false;
}
manager.dispatchProduct(p, loggedUser);
return true;
}
Fachada de listado y venta: Objeto de transferencia
public static class ProductBean{
private Collection products;
private Collection userProducts;
public Collection getProducts () {
return products;
}
public Collection getUserProducts () {
return userProducts;
}
public void setProducts(Collection collection) {
products = collection ;
}
public void setUserProducts(Collection collection) {
userProducts = collection ;
}
}
Clientepublic class Client {
ClientView view;
public void showProducts(){
view.showProducts();
}
}
class ClientView{
private ClientHelper helper = new ClientHelper();
public void showProducts(){
Iterator it = helper.getProducts().iterator();
while (it.hasNext())
System.out.println(it.next());
}
}
View
Helper
54
Cliente
class ClientHelper{
private ProductFacade facade = new ProductFacade();
public Collection getProducts(){
Collection c = new Vector();
ProductBean bean = facade.listProducts();
c.addAll(bean.getUserProducts());
c.addAll(bean.getProducts());
return c;
}
}
Conclusiones
l Clara separación de tareas.l Posibilidad de distribuir objetos.l Definición de paquetesl Las únicas clases publicas son “User”, “Product” y
“ProductFacade”.l El cliente se define en un paquete distinto.l El cliente solo puede acceder a la fachada.
Resumen
l Factoryl Singletonl View Helperl Session Facadel Data Access Object