Programacion en Java
-
Upload
jorge-guillo -
Category
Documents
-
view
953 -
download
7
description
Transcript of Programacion en Java
Programación en Java
Jorge Guilló – [email protected]
Contenido Java
Introducción Primer programa Programación básica Programación orientada a objetos Excepciones Archivos JAR
API Java Fechas y cadenas Colecciones Tratamiento de ficheros Redes Programación multihilo
Acceso a datos (JDBC) Arquitectura Conexiones Comandos y consultas Transacciones
Introducción a Java
Origen y arquitectura de Java
Yo soyDuke!
Origen de Java Deriva de C y C++ Creado por James Gosling y otros
ingenieros de Sun Microsystems Se creó en 1991 en sólo 18 meses
Primero se llamó Oak Se creó para dispositivos electrónicos ante
la necesidad de crear un lenguaje independiente de la plataforma
En 1994 cambia su orientación hacia Internet Se utiliza el nombre Java
JDK 1.0 aparece en 1996
Tipos de Aplicaciones en Java Con Java se pueden hacer varios
tipos de aplicaciones: Aplicaciones normales Applets Componentes JavaBeans Servlets JSP Enterprise Java Beans (EJB)
Código binario (ByteCode) Genera bytecode, no es código
ejecutable La máquina virtual Java (JVM) ejecuta el
bytecode Se necesita una JVM para cada
plataforma Lento pero seguro Compilador Just-In-Time (JIT) La JVM utiliza cargadores de clases para
obtener los bytecodes del disco o de la red
Características de Java Simple Orientado a
Objetos El núcleo API Robusto Multihilo
Gestión de memoria
Arquitectura neutral
Interpretado y de alto rendimiento
Distribuido
Ediciones de Java 2 JDK Micro Edition (J2ME)
Para dispositivos electrónicos JDK Standard Edition (J2SE)
Para ordenadores de sobremesa JDK Enterprise Edition (J2EE)
Para empresas Java Server Pages Servlets Java support for XML Enterprise JavaBeans (EJB)
El Kit de desarrollo de Java
(JDK Standard Edition) Gratis Versiones del JDK: 1.0, 1.1, 1.2,
1.3, 1.4, 1.5 Se compone de las librerías
estándar (clases o APIs) y utilidades: Compilador: javac miFichero.java Intérprete: java miFichero.class
appletviewer miFichero.class
Documentador: javadoc miFichero.java
Entorno de ejecución (JRE)
Gratis Permite ejecutar cualquier
aplicación Java en el cliente Se compone de las librerías
estándar (clases o APIs) y el intérprete
Java Plug-in Hace que los applets y los componentes
JavaBeans los ejecute el JRE que tenga instalado el cliente en vez de la máquina virtual del navegador
Tiene como ventaja el poder utilizar las novedades de la última versión
Instalación automática, aparece un icono en el panel de control
Para que funcione hay que cambiar las etiquetas de los applets con la utilidad HtmlConverter.bat del JDK
La máquina virtual Java (JVM) CPU por software que tiene los
bytecodes por juego de instrucciones Los bytecodes son de la forma:
<opcode><...parámetros> La JVM verificará aquellos bytecodes
que hayan atravesado la red El intérprete traduce los bytecodes a
instrucciones específicas del sistema operativo/hardware
Escrita en C, C++ o ensamblador
Rendimiento JVM más lenta que los ejecutables
tradicionales: El proceso de verificación lleva su tiempo Conversión de los bytecodes a instrucciones de
máquina nativa Múltiples chequeos de seguridad Las instrucciones de Java son código del
tamaño de un byte Java se ha implementado como una máquina
de pila en la memoria Garbage collection
Seguridad No hay punteros
Garbage Collection Hay tres componentes principales:
El verificador de código Se asegura que los bytecodes se ajustan a la
especificación de JVM. El cargador de clases
Recupera las clases de la red, guardando las de cada servidor en un sitio diferente para evitar interferencias
El gestor de seguridad Chequea la política de seguridad, es decir, se
determina que actividades puede realizar la JVM y bajo que circunstancias
Entornos de programación JDK + editor
Notepad TextPad UltraEdit JEdit Emacs
IDE completo Eclipse NetBeans Borland JBuilder IBM Websphere Oracle JDeveloper BEA WebLogic
Workshop Xinox JCreator
Primer programa en Java
// fichero HolaMundo.javaclass HolaMundo { public static void main(String args[]) {
System.out.println("Hola mundo!"); } // fin de main()} // fin de class HolaMundo
// fichero HolaMundo.javaclass HolaMundo { public static void main(String args[]) {
System.out.println("Hola mundo!"); } // fin de main()} // fin de class HolaMundo
Uy! Un HolaMundo!
Qué original....
Primer programa en Java Compilación
javac HolaMundo.java -d <dir.destino> -sourcepath
<dir.fuentes> -classpath
<dir.librerias>
Genera código intermediointerpretable por la máquina virtual (bytecode)
HolaMundo.class
Código fuente
Bytecode
100101011101
class Hopublic vo
HolaMundo.java______________________
Esto estará en un
segundito…
Primer programa en JavaEjecución
java HolaMundo -classpath <dir.clases>
Ejecuta la clase en la máquina virtual
Busca un método public static void main(String args[]) dentro de la clase y lo ejecuta
Se debe proporcionar la ruta de acceso a todas las clases que se utilicen dentro del programa
HolaMundo.class
Hola m
undo!
Programación Java
Programación básica
Ficheros java
Una sola clase pública por fichero Al compilar se genera un .class por
cada clase (pública o privada)
Comentarios Una línea
// Comentario Multilinea
/* Comentario Comentario */
Comentario para documentación /** * Comentario JavaDoc */
Variables Declaración de variable
int i; Declaración múltiple
int a,b,c; Asignación de variable
i = 5; Declaración + asignación
int i = 5;
Visibilidad de variables
Los bloques de código (llaves) definen el alcance de las variables
void funcion(int x) {int y = 5;if (x == y) {
int z = x + y;}System.out.println(x);System.out.println(y);System.out.println(z); // Error
}
void funcion(int x) {int y = 5;if (x == y) {
int z = x + y;}System.out.println(x);System.out.println(y);System.out.println(z); // Error
}
Tipos de datos
Básicos (por valor) boolean byte, short, int, long float, double char (Unicode)
Clases (String es una clase) Matrices (arrays)
Expresiones Literales
Numéricos 4, 071, 0xFF, -4.5, 5e6 3L, 4.5F
Booleanos true false
Carácter 'A'
Cadena "Hola" "Dos\nLineas"
Operadores Aritméticos + - * / %
Comparación == != > >= < <=
Lógicos& && | || ^ !
De Bit& | ^ ~ << >> >>>
Asignación= ++ -- += -= ...
Condicional?:
Conversión de tipos
Ensanchamiento: Conversión a un tipo más grande La conversión es automática
long l = 65;
Estrechamiento: Conversión a un tipo más pequeño Se necesita utilizar el operador de
cast int i = (int)l;
Sentencias condicionales
¿..?
if (a>b) {// Código
}else {
// Código}
if (a>b) {// Código
}else {
// Código}
switch (i) {
case 0:
//Código
break;
default:
//Código
break;
}
switch (i) {
case 0:
//Código
break;
default:
//Código
break;
}
Bucles
for (i=0;i<10;i++){// Código
}
for (i=0;i<10;i++){// Código
}
do {
// Código
} while (i>0);
break; Terminar bucle
continue; Siguiente iteración
do {
// Código
} while (i>0);
break; Terminar bucle
continue; Siguiente iteración
while (i > 0) {// Código
}
while (i > 0) {// Código
}
Matrices Las matrices son objetos de la clase Array Declaración:
String[] palabras; String palabras[];
Creación: String[] palabras = new String[5]; String[] palabras = { "Hola", "mundo" }
Acceso a elementos: palabras[0] = "Adiós";
Obtener tamaño: int tam = palabras.length;
Los índices válidos van desde 0 a .length - 1
Matrices multidimensionales Se utilizan matrices de matrices
int[][] matriz = new int[4][4]; matriz[0][0] = 3;
.length devuelve el tamaño de la primera componente, no el tamaño total de la matriz
Se pueden crear matrices no uniformes int[][] matriz = new int[3][]; matriz[0] = new int[2]; matriz[1] = new int[3]; matriz[2] = new int[1];
0:
1:
2:
Programación Java
Programación orientada a objetos
Clases
La clase es el núcleo de Java Una clase define un nuevo tipo de
dato Una clase es una plantilla para un
objeto Un objeto es una instancia de una
clase A las propiedades y los métodos se
les llama miembros de la clase
Forma general de una clase
class NombreClase {tipo variable1;tipo variable2;
tipo metodo1(parámetros) {// cuerpo del método
}tipo metodo2(parámetros) {
// cuerpo del método}
}
class NombreClase {tipo variable1;tipo variable2;
tipo metodo1(parámetros) {// cuerpo del método
}tipo metodo2(parámetros) {
// cuerpo del método}
}
Ejemplo de clase
La clase más pequeña podría ser así:class MiClase {
// la máquina virtual llama al método main()
public static void main (String args[]) {
System.out.println(“Hasta luego Lucas”);
}
}
class MiClase {
// la máquina virtual llama al método main()
public static void main (String args[]) {
System.out.println(“Hasta luego Lucas”);
}
}
El punto de entrada a la aplicación es a través del método main( ) que es llamado por la JVM
Una clase sencilla Creación de la clase
class Caja {
double ancho;
double alto;
double fondo;
}
class Caja {
double ancho;
double alto;
double fondo;
}
Creación del objeto a partir de esa claseCaja objCaja;
objCaja = new Caja();
// también: Caja objCaja = new Caja();
objCaja.ancho = 20.4;
objCaja.alto = objCaja.fondo = 30.3;
Caja objCaja;
objCaja = new Caja();
// también: Caja objCaja = new Caja();
objCaja.ancho = 20.4;
objCaja.alto = objCaja.fondo = 30.3;
HEAP
Pointx=10 y=10
Pointx=5 y=10
PILA
Referencias a objetos Las variables de tipo objeto almacenan
referencias El objeto se almacena en el "montón" (heap) Una referencia nula (p.ej. antes de crear el objeto) se
indica con la palabra clave null La asignación entre objetos copia la
referencia, no el contenido del objeto Point p1; p1 = new Point(10,10); Point p2; p2 = p1; p1.x = 5
p1:p2:
Nomenclatura Java Por convención, en Java se utilizan las siguientes reglas
para identificadores: Clases e interfaces: Mayúsculas cada palabra
class MiClaseRectangulo {...} Miembros, variables y parámetros: Minúsculas la primera
palabra, mayúsculas las siguientes void escribeEntero(int entero) {...} int numLinea;
Paquetes: Todo minúsculas (no se suele utilizar más de una palabra)
package com.miempresa.proyecto; Constantes: Todo mayúsculas (con subrayados entre
palabras) final double PI = 3.141592; final int VELOCIDAD_LUZ = 299792458;
Métodos Forma general de un método:
tipo nombreMetodo(tipo1 param1, tipo2 param2) {// cuerpo del metodo
} Si no devuelve resultado se indica void como tipo
del método Para devolver un valor:
return valor; Ejemplo:
double volumen( ) {return ancho * alto * fondo;
}
Constructores
Método que ejecuta el operador new
Si no existe, java crea uno por defecto
Para tareas de inicialización Ejemplo:
Caja( ) {
ancho = alto = fondo = 0;
}
Caja( ) {
ancho = alto = fondo = 0;
}
this Para acceder al propio objeto, se utiliza this
Acceso a miembros con nombre conflictivo
Llamada a otros constructores
Pasar el propio objeto como parámetro
int valor;int setValor (int valor) {this.valor = valor;
}
int valor;int setValor (int valor) {this.valor = valor;
}
Caja(Caja c) {this(c.alto,c.ancho,c.fondo);
}
Caja(Caja c) {this(c.alto,c.ancho,c.fondo);
}
void Guardar(ArrayList lista) {lista.add(this);
}
void Guardar(ArrayList lista) {lista.add(this);
}
Sobrecarga de métodos Dos o más métodos dentro de la misma clase
con el mismo nombre y distintos parámetros
float incremento (float valor) {
return Math.abs(valor) * 1.16;
}
double incremento (double valor) {
return Math.abs(valor) * 1.16;
}
float incremento (float valor) {
return Math.abs(valor) * 1.16;
}
double incremento (double valor) {
return Math.abs(valor) * 1.16;
}
También se pueden sobrecargar los constructores
Cuando se invoca un método sobrecargado, Java utiliza el tipo y/o el nº de argumentos para saber a qué método llamar
Parámetros
Se pueden pasar objetos a los métodos como parámetros
Un tipo simple se pasa por valor (byte, short, int, long, char, float, double, boolean)
Un objeto se pasa por referencia (arrays, Strings, etc.)
Los métodos pueden devolver objetos
Control de acceso Modificadores de acceso de los
miembros: public
Los miembros pueden ser accedidos desde cualquier parte del programa
private Los miembros sólo pueden ser accedidos desde
dentro de la misma clase protected
Los miembros pueden ser accedidos desde otro paquete pero a clases que sean subclases directas de su clase
nada (por defecto) Los miembros sólo pueden ser accedidos desde
dentro del mismo paquete
Protección de acceso
Acceso a miembros de una clase:
Desde private nada(package)
protected public
Misma clase Sí Sí Sí Sí
Subclase del mismo paquete No Sí Sí Sí
No subclase del mismo paquete No Sí Sí Sí
Subclase de diferente paquete No No Sí Sí
No subclase de diferente paquete No No No Sí
Métodos accesores (propiedades) Las variables de instancia se suelen declarar
privadas Se añaden métodos getXXX() y setXXX() para
obtener y establecer el valor de dichas variablespublic class Propiedades {
private int valor;
public int getValor() {
return this.valor;
}
public void setValor(int valor) {
this.valor = valor;
}
}
public class Propiedades {
private int valor;
public int getValor() {
return this.valor;
}
public void setValor(int valor) {
this.valor = valor;
}
}
static Métodos static:
Se puede llamar a un método static o a una variable static sin crear el objeto de la clase
Variables static: Las variables static actúan como variables
globales (todas las instancias de la clase comparten la misma variable static)
Bloques de código static: Es lo primero que se ejecuta, incluso antes
que el constructor
Método main Una aplicación Java necesita contener al
menos una clase ejecutable Para poder ejecutar una clase Java, ésta debe
definir un método main con la siguiente signatura:
public static void main (String arg[]) {...} Debe ser público, accesible desde fuera del paquete Debe ser estático, ya que no se va a crear ningún
objeto para lanzar el método No devuelve ningún resultado (void) Recibe como parámetro un vector de cadenas, que
corresponden a los argumentos de línea de comandos que se proporcionan a la aplicación al ejecutarla
Herencia
Se define una clase padre (superclase) que da características comunes (variables y métodos) a todas sus clases hijas (subclases)
Se utiliza la palabra clave extends No hay limite en el nivel de
profundidad de la herencia Java no soporta herencia múltiple
Ejemplo de herencia
class A {int i, j;void verij() {
System.out.println(“i: “ + i + “, j: “ + j);}
}
class B extends A {int k;void verijk() {
System.out.println(“i: “ + i + “, j: “ + j + “, k: “ + k);
}}
class A {int i, j;void verij() {
System.out.println(“i: “ + i + “, j: “ + j);}
}
class B extends A {int k;void verijk() {
System.out.println(“i: “ + i + “, j: “ + j + “, k: “ + k);
}}
Conversión de referencias Se puede asignar una referencia a un objeto a
una referencia de un tipo compatible Clase en la jerarquía de clases base Interfaz implementado por el objeto
Ensanchamiento: Conversión de un tipo derivado a un tipo base o interfaz
Se puede realizar la asignación directamente String s = "Hola"; Object obj = s;
Estrechamiento: Conversión a un tipo derivado Se debe utilizar el operador de cast
s = (String)obj;
super
Acceso a miembros de la clase base Llamar al constructor de la
superclase:super(parámetros) Si no se llama explícitamente a un
constructor de la clase base, Java añade la llamada al constructor por defecto super()
Acceder a un miembro de la superclase:super.miembro
Sobreescritura de métodos
Un método de una subclase que tiene el mismo nombre y parámetros que la superclase Cambia la implementación
proporcionada por la clase base Sobrecarga de métodos: Varios
métodos con el mismo nombre pero diferentes parámetros
Polimorfismo Se llama polimorfismo a tener un mismo
método con distintas implementaciones Se consigue a través de la
sobreescritura de los métodos
Vehiculo v = new Moto();
v.Frenar( );
v = new Coche();
v.Frenar( );
Vehiculo v = new Moto();
v.Frenar( );
v = new Coche();
v.Frenar( );
Las llamadas son iguales, pero la implementación que se ejecuta es distinta
Clases abstractas Proporcionan una implementación
parcial de la clase Los métodos no implementados se
declaran como abstract y la clase tambiénabstract tipo nombreMetodo(parámetros);
Una subclase de una clase abstracta debe implementar todos los métodos abstractos o declararse como abstracta
No se pueden crear objetos de clases abstractas
final Usos de la palabra clave final:
Para definir constantes
Para evitar la sobreescritura
Para evitar la herencia
final int cancel = 2;final int cancel = 2;
final void metodo( ) {
// cuerpo del método
}
final void metodo( ) {
// cuerpo del método
}
final class A {
// cuerpo de la clase
}
final class A {
// cuerpo de la clase
}
La clase Object
Es una clase definida por Java Todas las demás clases son
subclases de Object Métodos importantes de la clase
Object: clone( ) para clonar un objeto
equals( ) para comparar contenido de objetos
toString( ) para visualizar un objeto
Asignar tipos primitivos a Object
Para cada tipo primitivo, existe una clase asociada que lo representa. Para poder asignar un valor de tipo
primitivo a una variable de tipo Object hay que construir un objeto de la clase correspondiente
Se puede recuperar el valor primitivo a partir del objetoint i = 5;
Object obj = new Integer(i);
Integer objInt = (Integer)obj;
i = objInt.intValue();
int i = 5;
Object obj = new Integer(i);
Integer objInt = (Integer)obj;
i = objInt.intValue();
Novedades JDK 1.5
Autoboxing: Conversión automática de tipos primitivos a sus clases correspondientes
Integer i = 3;
int j = i;
Integer i = 3;
int j = i;
Conversión número-cadena Los objetos de encapsulación de tipos primitivos
proporcionan además métodos estáticos de conversión a y desde cadena
Convertir número a StringString st = String.valueOf(2);
String st = Double.toString(2);
String st = Float.toString(2);
String st = Long.toString(2);
String st = Boolean.valueOf("true").toString();
String st = String.valueOf(2);
String st = Double.toString(2);
String st = Float.toString(2);
String st = Long.toString(2);
String st = Boolean.valueOf("true").toString();
Convertir String a número
double d = Double.valueOf("2").doubleValue();
float f = Float.valueOf("2").floatValue();
long l = Long.valueOf("2").longValue();
double d1 = Double.parseDouble("2");
float f = Float.parseFloat("2");
long l = Long.parseLong("2");
double d = Double.valueOf("2").doubleValue();
float f = Float.valueOf("2").floatValue();
long l = Long.valueOf("2").longValue();
double d1 = Double.parseDouble("2");
float f = Float.parseFloat("2");
long l = Long.parseLong("2");
Interfaces Permite abstraer completamente la interfaz de
una clase utilizando la palabra clave interface
Una clase puede implementar cualquier número de interfaces a través de la palabra clave implements
Cada clase que implemente una interfaz, debe implementar todos los métodos de la interfaz
Si una clase implementa una interfaz pero no implementa todos los métodos, tiene que ser abstract
Se pueden utilizar interfaces para importar constantes. PERO NO ES RECOMENDABLE
Las interfaces se pueden extender
Herencia vs Interfaces
Herencia de clasesImplementación
de interfaces
Sólo se puede tener una clase baseSe pueden implementar todos los interfaces que se quiera
Una clase base puede tener cualquier tipo de miembros
Un interfaz sólo puede tener constantes, variables estáticas y métodos
La clase base puede proporcionar implementación a los métodos
Un interfaz sólo aporta la definición del método, no su implementación
Se puede crear directamente un objeto de la clase base (salvo clases abstractas)
No se puede crear directamente un objeto de tipo interfaz
Novedades JDK 1.5 Enumerados:
enum Color { rojo, azul, verde, amarillo } Son clases, por lo que se les pueden añadir variables y métodos
import static: Permite acceder a miembros estáticos de una clase sin el nombre de la clase
public enum Moneda { pela(1), duro(5), chapa(25), libra(100); Moneda(int value) { this.value = value; } private final int value; public int value() { return value; } }
public enum Moneda { pela(1), duro(5), chapa(25), libra(100); Moneda(int value) { this.value = value; } private final int value; public int value() { return value; } }
import static java.lang.System.*;
class Consola { public void Escribir(String s) { out.println(s); }}
import static java.lang.System.*;
class Consola { public void Escribir(String s) { out.println(s); }}
Paquetes Es un conjunto de clases agrupadas bajo un
nombre Permiten dar a 2 clases el mismo nombre
siempre que estén en diferentes paquetes Para crear un paquete se utiliza la palabra
clave package como primera línea del código fuentepackage paquete1;
La jerarquía de paquetes coincide con la estructura de directorios
package java.awt.imagen; Carpeta: java\awt\imagen
Los paquetes se deben organizar de forma lógica
La variable de entorno CLASSPATH Sirve para decirle al compilador y al intérprete donde
deben buscar las clases que se utilizan en el programa:Set CLASSPATH=.;c:\MiJava\MisPaquetes;IMPORTANTE: si no se añade el . (punto) en el classpath, no
encuentra las clases aunque estemos dentro del mismo directorio También es necesario definir el classpath para el jdk y
alguna variable más:Set CLASSPATH = .;C:\j2sdkee1.3.1\lib\j2ee.jar;C:\j2sdkee1.3.1\lib\
j2eetools.jar;Set JAVA_HOME = C:\jdk1.3.1_02Set J2EE_HOME = C:\j2sdkee1.3.1Set J2EE_CLASSPATH = C:\j2sdkee1.3.1\lib\system\ifxjdbc.jar // para Informix
Probablemente también sea necesario alguna otra variable para el entorno de desarrollo que estemos utilizando:
Set FORTE4J_HOME = C:\forte4j // para el entorno Forte de Sun
Importar paquetes La palabra clave import nos permite importar
clases que residen en otros paquetes
Esta sentencia no es necesaria, se puede indicar en cada clase a qué paquete pertenece
import paquete1.*;
import java.util.Date;
class MiFecha extends Date {
// código de la clase
}
import paquete1.*;
import java.util.Date;
class MiFecha extends Date {
// código de la clase
}
class MiFecha extends java.util.Date {
// código de la clase
}
class MiFecha extends java.util.Date {
// código de la clase
}
Gestión de errores
Hay dos clases de error en Java: Exception: Errores recuperables Error: Errores graves no recuperables
Throwable
Exception Error
Capturar excepciones
Para detectar si se produce una excepción se utiliza la construcción
Se puede indicar la clase concreta de excepción que se quiere capturartry {
// Código que se prueba
} catch (Exception e) { // Código si hay excepción
}
try { // Código que se prueba
} catch (Exception e) { // Código si hay excepción
}
Orden de los catch
Cuando se produce una excepción, el flujo de programa entra en el primer catch que capture una clase de excepción compatible
Se deben ordenar los catch poniendo primero las excepciones más específicas
try {int a = 5;int b = 0;int c = a/b;
} catch (ArithmeticException ae){
System.out.println("Error aritmetico);
} catch (Exception e){
System.out.println("Error inesperado: "
+ e.getMessage());}
try {int a = 5;int b = 0;int c = a/b;
} catch (ArithmeticException ae){
System.out.println("Error aritmetico);
} catch (Exception e){
System.out.println("Error inesperado: "
+ e.getMessage());}
finally Hay operaciones que se quieren realizar
tanto si hay error como si todo va bien Ejemplo: Cerrar una conexión a BD
Se utiliza la cláusula finally El bloque finally siempre se ejecuta
try {
// ...
} catch (Exception ex) {
// Se ejecuta si hay error
} finally {
// Siempre se ejecuta
}
try {
// ...
} catch (Exception ex) {
// Se ejecuta si hay error
} finally {
// Siempre se ejecuta
}
Propagación de excepciones Si una excepción no se captura, se
propaga al método anterior en la pila de llamadas
Los métodos que pueden producir excepciones contienen la cláusula throws void metodo(int a) throws IOException {...}
Cuando se llama a un método que tiene cláusula throws, existen dos opciones: Capturar la clase de excepción indicada Incluir una cláusula throws para la
excepción
Excepciones propias Se puede crear una clase propia de excepción,
construyendo una clase derivada de Exception Normalmente se sobreescriben los métodos getMessage() y toString()
Por convención, el nombre de una clase de excepción suele terminar con la palabra Exception
Para lanzar la excepción se utiliza la instrucción throw
throw new MiException();
public class MiException() extends Exception{
public string getMessage() {return "Error propio";
}}
public class MiException() extends Exception{
public string getMessage() {return "Error propio";
}}
Archivos JAR Las aplicaciones y librerías Java se suelen
empaquetar en archivos JAR Formato ZIP Contienen toda la estructura de clases
(ficheros .class) Incluyen un fichero de información
META-INF/Manifest.mf (fichero de manifiesto) Pueden incluir ficheros adicionales
Los archivos JAR se pueden ejecutar directamente o especificar como rutas de ClassPath
Fichero de manifiesto Ejemplo de fichero manifest.mf
IMPORTANTE: Terminar todas las líneas con salto de linea
Para aplicaciones ejecutables, el atributo Main-Class indica cual es la clase que contiene el método main (punto de entrada de la aplicación)
Manifest-Version: 1.0Created-By: 1.5.0-rc (Sun Microsystems Inc.)Main-Class: paquete.App
Manifest-Version: 1.0Created-By: 1.5.0-rc (Sun Microsystems Inc.)Main-Class: paquete.App
Tratamiento de archivos JAR
Crear archivo JAR: Se utiliza jar.exe Crear un jar con el contenido del
directorio jar cvf fichero.jar .
Indicar el fichero de manifiesto jar cvfm fichero.jar MiManifiesto .
Ejecutar archivo JAR java –jar fichero.jar
API Java: Fechas
Date La clase java.util.Date representa un
instante en el tiempo, con precisión de milisegundos Date d = new Date();
Fecha / hora actual La mayoría de los métodos de esta
clase están desaconsejados (deprecated) en favor de las clases Calendar y DateFormat getTime y setTime convierten la fecha en
un número de milisegundos (long) compareTo permite comparar fechas
Calendar (GregorianCalendar) java.util.Calendar es una clase abstracta con
métodos para obtener y establecer los valores de una componente de una fecha/hora
Los objetos Calendar se crean con una factoría (metodo estático que crea objetos del propio tipo)
Calendar c = Calendar.getInstance(); Devuelve la fecha/hora actual
La subclase concreta que se utiliza normalmente es GregorianCalendar
En la mayoría de los casos, se puede utilizar Calendar en lugar de Date
Componentes de una fecha El método get devuelve un componente de la
fecha/hora int year = c.get(Calendar.YEAR);
El método set establece el valor de un componente c.set(Calendar.DAY_OF_MONTH,15);
Componentes de la fecha: MILLISECOND, SECOND, MINUTE, HOUR, AM_PM,
DATE, DAY_OF_MONTH, DAY_OF_WEEK, WEEK_OF_MONTH, WEEK_OF_YEAR, MONTH, YEAR, ERA
ATENCIÓN: Los meses van de 0 a 11, no de 1 a 12 Por claridad, es recomendable utilizar las constantes
Calendar.JANUARY ... Calendar. DECEMBER getTimeInMillis() devuelve la fecha/hora como un
número de milisegundos (como Date.getTime())
DateFormat java.text.DateFormat es una clase abstracta que
permite convertir valores de fecha a cadena y viceversa Los objetos se crean por medio de una factoría
DateFormat f = DateFormat.getDateInstance(); Para trabajar con fechas
DateFormat f = DateFormat.getTimeInstance(); Para trabajar con horas
DateFormat f = DateFormat.getDateTimeInstance(); Para trabajar con fecha/hora
El método parse convierte cadenas a fechas (Date) Date d = f.parse("31/10/1975");
El método format convierte fechas a cadenas String s = f.format(d);
SimpleDateFormat Para forzar una determinada representación
de fecha se puede utilizar la clase derivada SimpleDateFormat
El formato de fecha-hora se establece como una cadena de texto
Al crear el objeto SimpleDateFormat f = new SimpleDateFormat("dd/MM/yyyy");
Con el método applyPattern f.applyPattern("dd/MM/yyyy hh:mm");
Después se utilizan los métodos estándar de DateFormat para realizar las conversiones
API Java: Cadenas
String
La clase String sirve para almacenar cadenas de texto Unicode
Las cadenas de texto son inmutables. No se pueden modificar directamente. Por eso es seguro realizar
asignaciones entre variables String
Operaciones con String I Longitud
i = s.length(); Concatenación
s3 = s1 + s2; s3 = s1.concat(s2);
Comparación b = s1.equals(s2); b = s1.equalsIgnoreCase(s2); i = s1.compareTo(s2); i = s1.compareToIgnoreCase(s2); b = s1.startsWith(s2); b = s1.endsWith(s2);
Operaciones con String II Obtener carácter
c = s.charAt(0); Obtener subcadena
s2 = s1.substring(i1,i2); Quitar espacios
s2 = s1.trim(); Buscar subcadenas
i = s1.indexOf(s2); i = s1.lastIndexOf(s2);
Reemplazos s4 = s1.replaceAll(s1,s2); s4 = s1.replaceFirst(s1,s2);
Operaciones con String III Construcción
s = String.format("Nº: %d",i); s = String.valueOf(i);
Conversión mayúsculas/minúsculas s2 = s1.toLowerCase(); s2 = s1.toUpperCase();
Pasar a matriz de char char[] c = s.toCharArray();
Dividir en partes String[] palabras = s.split(" ");
Concatenación masiva La operación de concatenación es muy
costosa: 1.- Reserva memoria para la cadena final 2.- Copia el contenido de la primera cadena 3.- Copia el contenido de la segunda cadena
Si esta operación se repite muchas veces con una misma cadena, el rendimiento se degrada exponencialmente
StringBuffer / StringBuilder
La clase StringBuffer representa un string modificable. Se puede modificar su contenido
directamente, sin copiar los contenidos
Cuando se queda sin memoria, reserva el doble
Métodos StringBuffer I length()
Devuelve la longitud de la cadena contenida setLength()
Establece la longitud Se rellena con el carácter nulo '\u0000'
capacity() Devuelve el tamaño reservado
ensureCapacity(n) Reserva al menos la capacidad indicada
setCharAt(pos,c) Modifica el carácter situado en la posición pos
Métodos StringBuffer II append(s)
Añade una cadena al final Sobrecargado para cualquier tipo de datos
insert(pos,s) Inserta una cadena en una posición determinada Sobrecargado para cualquier tipo de datos
delete(pos1,pos2) Elimina los caracteres desde la posición pos1 a pos2-1
replace(pos1,pos2,s) Sustituye los caracteres desde la posición pos1 a pos2–1 por la cadena s
reverse() Invierte el orden de los caracteres
Práctica String vs StringBuffer Realizar un bucle de 10000 iteraciones
que va concatenando un carácter a una cadena Implementarlo con concatenación de String Implementarlo con StringBuffer
Medir el tiempo que tarda en realizar la operación con cada método
Cambiar el número de iteraciones y comprobar el impacto en el rendimiento
API Java: Colecciones
Java Collections Framework Está basado en una jerarquía de
interfaces, pertenecientes al paquete java.util
Interfaces de colecciones Collection: Representa un grupo de
objetos Sin implementación directa
Set: Colección desordenada que no puede contener duplicados
List: Colección ordenada (secuencia) que puede contener duplicados
Map: Objeto que almacena pares clave-valor No puede haber claves duplicadas Una clave corresponde con un único valor
Ordenación de elementos Se pueden construir colecciones
ordenadas de elementos Los elementos implementan la interfaz
Comparable Utilizando un objeto que implemente la
interfaz Comparator SortedSet: Set que mantiene sus
elementos ordenados con un Comparator
SortedMap: Map que mantiene sus elementos ordenados con un Comparator
Collection Operaciones básicas
int size() boolean isEmpty(); boolean contains(Object element); boolean add(Object element); boolean remove(Object element); Iterator iterator();
Operaciones en bloque boolean containsAll(Collection c); boolean addAll(Collection c); boolean removeAll(Collection c); boolean retainAll(Collection c); void clear();
Conversión a matriz Object[] toArray(); Object[] toArray(Object a[]);
Iteradores Todas las colecciones se pueden recorrer con
un iterador que proporcionan. hasNext() permite saber si quedan elementos por
obtener next() devuelve el siguiente elemento de la
colección remove() elimina de la colección el último elemento
devuelto por next()Collection c = obtenerColeccion();for (Iterator i = c.iterator(); i.hasNext(); ){ if (i.next().equals("borrame")) {
i.remove();
}}
Collection c = obtenerColeccion();for (Iterator i = c.iterator(); i.hasNext(); ){ if (i.next().equals("borrame")) {
i.remove();
}}
Set No añade ningún método
específico Impementación: HashSet
SortedSet Añade los métodos:
Impementación: TreeSet
SortedSet subSet(Object fromElement, Object toElement);SortedSet headSet(Object toElement); SortedSet tailSet(Object fromElement); Object first(); Object last(); Comparator comparator();
SortedSet subSet(Object fromElement, Object toElement);SortedSet headSet(Object toElement); SortedSet tailSet(Object fromElement); Object first(); Object last(); Comparator comparator();
List Añade métodos de acceso por posición,
búsqueda y rango. Permite utilizar el iterador ListIterator
Impementaciones: ArrayList, LinkedList
Object get(int index); Object set(int index, Object element); void add(int index, Object element); Object remove(int index); boolean addAll(int index, Collection c);int indexOf(Object o); int lastIndexOf(Object o); ListIterator listIterator(); ListIterator listIterator(int index); List subList(int from, int to);
Object get(int index); Object set(int index, Object element); void add(int index, Object element); Object remove(int index); boolean addAll(int index, Collection c);int indexOf(Object o); int lastIndexOf(Object o); ListIterator listIterator(); ListIterator listIterator(int index); List subList(int from, int to);
ListIterator Permite ir hacia delante y hacia atrás,
insertar y modificar elementos
boolean hasNext(); Object next(); boolean hasPrevious(); Object previous(); int nextIndex(); int previousIndex(); void remove(); void set(Object o); void add(Object o);
boolean hasNext(); Object next(); boolean hasPrevious(); Object previous(); int nextIndex(); int previousIndex(); void remove(); void set(Object o); void add(Object o);
Map
Trabaja con pares clave-valor Operaciones básicas
Object put( Object key, Object value)Object get(Object key)Object remove(Object key)boolean containsKey( Object key); boolean containsValue( Object value); int size(); boolean isEmpty();
Object put( Object key, Object value)Object get(Object key)Object remove(Object key)boolean containsKey( Object key); boolean containsValue( Object value); int size(); boolean isEmpty();
Map Operaciones en bloque
Obtener colecciones asociadas
Implementación: HashMap
void putAll(Map t); void clear();
void putAll(Map t); void clear();
public Set keySet(); public Collection values(); public Set entrySet(); public interface Entry {
Object getKey(); Object getValue(); Object setValue(Object v); }
public Set keySet(); public Collection values(); public Set entrySet(); public interface Entry {
Object getKey(); Object getValue(); Object setValue(Object v); }
SortedMap Añade los métodos:
Implementación: TreeMap
Comparator comparator(); SortedMap subMap(Object fromKey, Object toKey); SortedMap headMap(Object toKey); SortedMap tailMap(Object fromKey); Object firstKey(); Object lastKey();
Comparator comparator(); SortedMap subMap(Object fromKey, Object toKey); SortedMap headMap(Object toKey); SortedMap tailMap(Object fromKey); Object firstKey(); Object lastKey();
Collections La clase Collections proporciona métodos
estáticos para realizar operaciones sobre coleccionessort(List l)sort(List l, Comparator c)shuffle(List l)shuffle(List l, Random r)binarySearch(List l, Object o)binarySearch(List l, Object o, Comparator c)reverse(List l)fill(List l, Object o)copy(List dest, List orig)max(Collection c)max(Collection c, Comparator cmp)min(Collection c)min(Collection c, Comparator cmp)
sort(List l)sort(List l, Comparator c)shuffle(List l)shuffle(List l, Random r)binarySearch(List l, Object o)binarySearch(List l, Object o, Comparator c)reverse(List l)fill(List l, Object o)copy(List dest, List orig)max(Collection c)max(Collection c, Comparator cmp)min(Collection c)min(Collection c, Comparator cmp)
Práctica: Agenda de teléfonos Aplicación de consola
que implemente una agenda de teléfonos
Cada registro de la agenda debe contener:
Nombre corto Nombre completo Dirección Teléfono E-mail
Se accede a los registros por el nombre corto
La aplicación debe permitir consultar, añadir, modificar y eliminar registros de la agenda
Opciones de menú: Listado de agenda Consultar registro Modificar registro Añadir registro Eliminar registro Salir
Novedades JDK 1.5 Tipos genéricos:
Todas las colecciones se pueden parametrizar con el tipo de elemento que contienenList<String> lista = new ArrayList<String>();lista.add("Hola");
Bucle for para iteradores Se añade una sintaxis alternativa para el bucle for
que permite recorrer de manera sencilla colecciones y matricesfor (String s : lista) { System.out.println(s);}
Tratamiento de ficheros
Clase File
Sirve para manejar directorios y ficheros Renombrar / Mover Borrar Crear directorios Listar ficheros Acceder a propiedades
Fecha modificación, tipo de archivo,…
Métodos de File
String getName()String getParent()long length()boolean renameTo(File dest)boolean delete()boolean canRead() / boolean canWrite()boolean exists()boolean mkdir()File[] list() / File[] listFiles()long lastModified() / void setLastModified(long t)boolean isDirectory()boolean isFile()boolean createNewFile()
String getName()String getParent()long length()boolean renameTo(File dest)boolean delete()boolean canRead() / boolean canWrite()boolean exists()boolean mkdir()File[] list() / File[] listFiles()long lastModified() / void setLastModified(long t)boolean isDirectory()boolean isFile()boolean createNewFile()
Ejemplo
File f1 = new File(“C:\\prueba.txt”);if (f1.exists()) {
f1.delete();}else {
f1.createNewFile();}File dir = new File(“C:\\”);File[] ficheros = dir.listFiles();for (int i=0; i<ficheros.length; i++) {
System.out.println(ficheros[i].getName());}
File f1 = new File(“C:\\prueba.txt”);if (f1.exists()) {
f1.delete();}else {
f1.createNewFile();}File dir = new File(“C:\\”);File[] ficheros = dir.listFiles();for (int i=0; i<ficheros.length; i++) {
System.out.println(ficheros[i].getName());}
Flujos de datos Paquete java.io Tenemos flujos de datos de una fuente a un
receptor Java soporta dos tipos de datos en los flujos:
Bytes Caracteres Unicode
Stream: cualquier tipo de secuencia de bytes que pueda ser leída o escrita
InputStream, OutputStream Reader: objeto para leer caracteres Unicode Writer: objeto para escribir caracteres Unicode
InputStream
Ofrece los siguientes métodos//lecturaint read()int read(byte[] buffer)int read(byte[] buffer, int offset, int length)
//cerrar flujovoid close()
//cantidad bytes disponiblesint available()
//descarta la cantidad de bytes especificadalong skip(long n)
//lecturaint read()int read(byte[] buffer)int read(byte[] buffer, int offset, int length)
//cerrar flujovoid close()
//cantidad bytes disponiblesint available()
//descarta la cantidad de bytes especificadalong skip(long n)
OutputStream
Ofrece los siguientes métodos
//escrituravoid write()void write(byte[] buffer)void write(byte[] buffer, int offset, int length)
//cerrar flujovoid close()
//fuerza la grabación en la salidavoid flush()
//escrituravoid write()void write(byte[] buffer)void write(byte[] buffer, int offset, int length)
//cerrar flujovoid close()
//fuerza la grabación en la salidavoid flush()
Reader
Ofrece los siguientes métodos//lecturaint read()int read(char[] cbuf)int read(char[] cbuf, int offset, int length)
//cerrar flujovoid close()
//si está disponible para leerboolean ready()
//descarta la cantidad de caracteres especificadalong skip(long n)
//lecturaint read()int read(char[] cbuf)int read(char[] cbuf, int offset, int length)
//cerrar flujovoid close()
//si está disponible para leerboolean ready()
//descarta la cantidad de caracteres especificadalong skip(long n)
Writer
Ofrece los siguientes métodos//escrituravoid write()void write(char[] cbuf)void write(char[] cbuf,int offset, int length)void write(String string)Void write(String string,int offset, int length)
//cerrar flujovoid close()
//fuerza la grabación en la salidavoid flush()
//escrituravoid write()void write(char[] cbuf)void write(char[] cbuf,int offset, int length)void write(String string)Void write(String string,int offset, int length)
//cerrar flujovoid close()
//fuerza la grabación en la salidavoid flush()
Flujos directos
Tipo Flujos de caracteres
Flujos de byte
Fichero FileReaderFileWriter
FileInputStreamFileOutputStream
Memoria(Array)
CharArrayReaderCharArrayWriter
ByteArrayInputStreamByteArrayOutnputStream
Memoria(String)
StringReaderStringWriter
N/A
Pipe PipeReaderPipeWriter
PipeInputStreamPipeOutputStream
Flujos de procesamiento Realizan conversiones a otro flujo También se les llama flujos de filtro Un flujo de entrada de filtro se crea con
una conexión a un flujo de entrada existente
Cuando leemos de él, accedemos a caracteres de otro flujo de entrada
Se usan para convertir una secuencia de datos más usable para la aplicación que está escribiendo
Lista de flujos de procesamiento
Tipo Flujo de caracteres
Flujo de Bytes
Buffering(mejora rendimiento)
BufferedReaderBufferedWriter
BufferedInputStreamBufferedOutputStream
Filtrado (clases abstractas)
FilterReaderFilterWriter
FilterInputStream FilterOutputStream
Conversión de bytes a caracteres
InputStreamReaderOutputStreamReader
Serialización de objetos ObjectInputStreamObjectOutputStream
Serialización de datos primitivos
DataInputStreamDataOutputStream
Soporte números de línea LineNumberReader LineNumberInputStream
Formateo de datos primitivos
PrintWriter PrintStream
Otros (no pertenecen a java.io):Cifrado / descifradoComprimir / descomprimir...
CipherInputStreamCipherOutputStreamInflaterInputStream DeflaterOutputStream
Un programa suele encadenar una serie de flujos para procesar los datos
Encadenamiento flujos de entrada
Encadenamiento flujos de salida
Cadenas de flujos
Data Source ProgramFileInputStream
BufferedInputStreamDataInputStream
Data SinkProgram
FileOutputStreamBufferedOutputStreamDataOutputStream
Ejemplo
//defino los flujos de entrada y salidaFileReader input = new FileReader(args[0]);FileWriter output = new FileWriter(args[1]);
char[] buffer = new char[128];int charsRead;
//leemos el primer buffercharsRead = input.Read(buffer);while(charsRead != -1){
output.write(buffer,0,charsRead);charsRead = input.Read(buffer);
}input.close();output.close();
//defino los flujos de entrada y salidaFileReader input = new FileReader(args[0]);FileWriter output = new FileWriter(args[1]);
char[] buffer = new char[128];int charsRead;
//leemos el primer buffercharsRead = input.Read(buffer);while(charsRead != -1){
output.write(buffer,0,charsRead);charsRead = input.Read(buffer);
}input.close();output.close();
Clase BufferedReader
Maneja el proceso de buffering Optimiza el rendimiento
Permite leer un flujo de texto línea a línea readLine()
Es un flujo de procesamiento
Ejemplo 2
FileReader input = new FileReader(args[0]);BufferedReader bufInput = new BufferedReader(input);
FileWriter output = new FileWriter(args[1]);BufferedWriter bufOutput = new BufferedWriter(output);
String line;
//leemos la primera línealine = bufInput.readLine();while(line != null){
bufOutput.write(line,0,line.length());bufOutput.newLine();line = bufInput.readLine();
}bufInput.close();bufOutput.close();
FileReader input = new FileReader(args[0]);BufferedReader bufInput = new BufferedReader(input);
FileWriter output = new FileWriter(args[1]);BufferedWriter bufOutput = new BufferedWriter(output);
String line;
//leemos la primera línealine = bufInput.readLine();while(line != null){
bufOutput.write(line,0,line.length());bufOutput.newLine();line = bufInput.readLine();
}bufInput.close();bufOutput.close();
Jerarquía clase InputStream
InputStream
FileInputStream
ObjectInputStream
PipedInputStream
SequenceInputStream
FilterInputStream
StringBufferInputStream
ByteArrayInputStream
DataInputStream
PushbackInputStream
BufferedInputStream
LineNumberInputStream
Jerarquía clase OutputStream
OutputStream
FileOutputStream
ObjectOutputStream
PipedOutputStream
FilterOutputStream
ByteArrayOutputStream
DataOutputStream
PushbackOutputStream
BufferedOutputStream
LineNumberOutputStream
FileInputStream / FileOutputStream
Podemos especificar la ruta del fichero del que queremos leer o escribir
FileInputStream: si el fichero no existe, da error
FileOutputStream: si el fichero existe, se sobrescribe
FileInputStream infile = new FileInputStream(“read.dat”);FileOutputStream outfile = new FileOutputStream(“write.dat”);
FileInputStream infile = new FileInputStream(“read.dat”);FileOutputStream outfile = new FileOutputStream(“write.dat”);
Jerarquía clase Reader
Reader
BufferedReader
PipedReader
InputStreamReader
FilterReader
StringReader
CharArrayReader
FileReader
PushbackReader
LineNumberReader
Jerarquía clase Writer
Writer
BufferedWriter
StringWriter
PipedWriter
FilterWriter
CharArrayWriter
FileWriterOutputStreamWriter
PrintWriter
InputSteamReader / OutputStreamReader
Podemos especificar la codificación de caracteres que vamos a leer, si es diferente a la local
ISO 8859-1 corresponde con ASCII + caracteres occidentales (acentos, ñ,...)
InputStreamReader ir = new InputStreamReader(System.in, “ISO-8859-1”);
InputStreamReader ir = new InputStreamReader(System.in, “ISO-8859-1”);
FileReader / FileWriter
Son análogas a encadenar: InputStreamReader
sobre FileInputStream OutputStreamWriter
sobre FileOutputStream Utilizan codificación de caracteres
por defecto
Redes
Sockets Son los puntos finales de una
comunicación entre procesos Para comunicarse por red, Java utiliza el
modelo de flujos Un socket puede tener asociados dos
flujos, uno de entrada y otro de salida Las conexiones socket TCP/IP están
implementadas en el paquete java.net
Configurar la conexión Una máquina debe ejecutar un
programa que esté esperando una conexión y otra debe intentar acceder a la primera
Debemos proporcionar la dirección a la que conectarnos y el puerto Los puertos van del 0 al 65535 Inferiores al 1024 están reservados
Para establecer la conexión las dos máquinas deben acordar el mismo puerto
Modelo de conexiones
Servidor
ServerSocket(puerto #)
ServerSocket.accept()
Socket()
OutputStream
InputStream
Socket.close()
Cliente
Socket(host,puerto #)(intenta conectarse)
OutputStream
InputStream
Socket.close()
Ejemplo Servidor TCP/IP
ServerSocket s = new ServerSocket(5432);
while (true){
Socket s1 = s.accept();
OutputStream s1out = s1.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s1out));
bw.write(“Hola”);
bw.close();
s1.close();
}
ServerSocket s = new ServerSocket(5432);
while (true){
Socket s1 = s.accept();
OutputStream s1out = s1.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s1out));
bw.write(“Hola”);
bw.close();
s1.close();
}
Ejemplo cliente TCP/IP
Socket s1 = new Socket(“127.0.0.1”,5432);
InputStream is = s1.getInputStream();
DataInputStream dis = new DataInputStream(is);
System.out.println(dis.readUTF());
dis.close();
s1.close();
Socket s1 = new Socket(“127.0.0.1”,5432);
InputStream is = s1.getInputStream();
DataInputStream dis = new DataInputStream(is);
System.out.println(dis.readUTF());
dis.close();
s1.close();
Programación multihilo
Hilos Paquete java.lang.Thread Un proceso es un programa en
ejecución Uno o más hilos constituyen un
proceso Un hilo está compuesto por:
Una CPU virtual El código que ejecuta la CPU Los datos sobre los que trabaja el
código
Creación de un hilo I Necesitamos una clase que implemente el interfaz
Runnableclass HolaRunner implements Runnable{
int i;
public void run(){
i = 0;
while(true) {
System.out.println(“Hola “ + i);
if (i==50) {
break;
}
}
}
}
class HolaRunner implements Runnable{
int i;
public void run(){
i = 0;
while(true) {
System.out.println(“Hola “ + i);
if (i==50) {
break;
}
}
}
}
Creación de un hilo II Ahora creamos un objeto de la clase Thread pasando como argumento una instancia de la clase HolaRunner
Un hilo siempre comienza su ejecución en el método run de su instancia Runnable cargada (r)
HolaRunner r = new HolaRunner();
Thread t = new Thread(r);
t.start();
HolaRunner r = new HolaRunner();
Thread t = new Thread(r);
t.start();
Multihilos Podemos crear tantos hilos como
queramos
Estos hilos comparten los mismos datos y el mismo código
Hasta que no ejecutamos el método start el hilo no comienza
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
Planificación de hilos Un hilo puede estar en varios estados:
Runnable Running Blocked
Se puede llamar al método sleep para parar el hilo Thread.sleep(10); // Milisegundos Pasaría a blocked
Finalización de un hilo
Cuando un hilo completa su ejecución no puede ejecutarse nuevamente
Si queremos, también podemos pararlo antes de que acabe Haremos que finalice el método Run
Métodos
boolean isAlive()
void setPriority()Thread.MIN_PRIORITYThread.NORM_PRIORITYThread.MAX_PRIORITY
void join()void join(long timeout)
Thread.sleep()Thread.yield()
boolean isAlive()
void setPriority()Thread.MIN_PRIORITYThread.NORM_PRIORITYThread.MAX_PRIORITY
void join()void join(long timeout)
Thread.sleep()Thread.yield()
Otra forma de crear hilos La clase Thread implementa el interfaz Runnable, por lo tanto se puede crear un hilo creando una clase que extienda de Thread
public class MyThread extends Thread{
public void run() {
...
}
}
... public static void main(String args[]) {
Thread t = new MyThread();t.start();
}
public class MyThread extends Thread{
public void run() {
...
}
}
... public static void main(String args[]) {
Thread t = new MyThread();t.start();
}
Palabra clave synchronized Podemos tener problemas si varios hilos
acceden a los mismos datos Necesitamos asegurarnos de que los
datos están en estado consistente antes de comenzar otro hilo
Al usar synchronized, comprobamos el estado del objeto Obtenemos la bandera de bloqueo asociada
al objeto
Ejemplo synchronized
public class Probando{
public void prueba(char c){
synchronized(this) {
datos[i] = c;
i++;
}
}
}
public class Probando{
public void prueba(char c){
synchronized(this) {
datos[i] = c;
i++;
}
}
}
Al ejecutar la orden synchronized, intenta obtener la bandera de bloqueo
Si no la consigue, el hilo para su ejecución hasta que la consiga
Uso synchronized Sólo funciona si todos los accesos a los
datos ocurren dentro de bloques sincronizados
Estos datos se deben declarar privatepublic void push(char c){
synchronized(this){
//código
}
}
ó
public synchronized push(char c){
//código
}
public void push(char c){
synchronized(this){
//código
}
}
ó
public synchronized push(char c){
//código
}
Bloqueo mutuo (Deadlock)
Ocurre cuando un hilo espera un bloqueo que tiene otro y ese otro espera un bloqueo que tiene el primero
Para prevenirlo, hay que establecer un orden en los bloqueos para obtenerlos y liberarlos en orden inverso
Métodos wait y notify Son métodos para comunicación entre
hilos wait: un hilo envía esta llamada, queda
pausado y libera el bloqueo notify: otro hilo notifica a un hilo
pausado que continúe El hilo despertado podrá obtener el bloqueo
nuevamente cuando se libere y continuará con la siguiente instrucción tras el wait
Para hacer estas llamadas tenemos que tener un bloqueo sobre el objeto Tienen que estar dentro de un bloque synchronized
Acceso a datos
JDBC
Acceso a datos JDBC 1.2
Tipos de drivers Carga de los Drivers Establecimiento de conexiones a BB.DD. Statements de JDBC. Manipulación del conjunto de resultados Mapeo de tipos entre SQL y Java Transacciones.
JDBC 2.0 JDBC 3.0
JDBC 1.2 Interfaces
CallableStatement Connection DatabaseMetaData Driver PreparedStatement ResultSet ResultSetMetaData Statement
Clases Date DriverManager DriverPropertyInfo Time TimeStamp Types
Excepciones DataTruncation SQLException SQLWarning
Relación entre clases
ResultSet
Tipos de Datos Date, Time,TimeStamp,
Numeric, etc.
Statement
PreparedStatement
CallableStatement
Connection
DriverManager
executeQuery
getMoreResults
prepareStatement
prepareCall
commit, abort
getXXXgetConnection
execute createStatement
setXXX
getXXX
Drivers JDBC Un driver JDBC es un módulo Java que
traduce los métodos estándar JDBC en llamadas a la base de datos de destino
Hay cuatro tipos de drivers distintos: Tipo 1 : Puente JDBC-ODBC Tipo 2 : API Nativo Tipo 3: Protocolo de red abierto (puro Java) Tipo 4: Protocolo de red propietario (puro
Java)
Driver tipo 1:Puente JDBC - ODBC
Cliente de BBDD Java
APIJDBC
Oracle
Oracle ODBC Driver
SQLServerSQLServer
Access
ODBCManager
SQLServer ODBC Driver Muy dependiente de la plataforma
Windows Requiere instalación en la máquina cliente Demasiadas capas: Impacto en la
eficiencia No apto para entornos de producción
ni de aplicaciones comerciales.
MS Access ODBC Driver
sun.jdbc.odbc.JdbcOdbcDriver
Driver tipo 2:API nativa
Cliente de BBDD Java
Controlador del Tipo2(código binario y Java) BBDD
APIJDBC
Protocolo específico del vendedor (SQL*Net, DB2, étc)
Implementado como una combinación de código nativo y Java
Muy dependiente de la plataforma
Requiere instalación en la máquina cliente
Driver tipo 3:Protocolo de red abierto
Cliente de BBDD Java
APIJDBC
Controlador JDBCTipo 3 (Java Puro)
Servidor Remotode Acceso a Base de Datos
Protocolo de Comunicaciones estándar (HTTP)
Oracle SQLServer Access
IDS Server (Intermediario)
Integramente en Java
Sin instalación
Aplicaciones inter/intranet
Driver tipo 4:Protocolo de red propietario
Integramente en Java
Sin instalación
Aplicaciones inter/intranet
Cliente de BBDD Java
APIJDBC
Controlador JDBCTipo 4 (Java Puro) Oracle
jdbc:oracle:thin:[<user>/<password>]@<host>:<port>:<sid>
oracle.jdbc.driver.OracleDriver
Protocolo de Red propietario: SQL*Net
Crear una conexión La clase DriverManager es la
responsable de cargar y descargar los controladores JDBC y crear conexiones Deduce el driver que se debe utilizar a
partir de la URL de conexión Para que DriverManager sea capaz de
utilizar un determinado driver JDBC, hay que cargarlo en memoria previamente
URL de conexión El formato de la URL de conexión depende del
driver Siempre comienza con jdbc:driver:
ODBC: sun.jdbc.odbc.JdbcOdbcDriver jdbc:odbc:NombreDSN
SQL Server: com.microsoft.jdbc.sqlserver.SQLServerDriver jdbc:microsoft:sqlserver://localhost:1433;
DatabaseName=Northwind;SelectMethod=cursor; Oracle: oracle.jdbc.driver.OracleDriver
jdbc:oracle:thin:@localhost:1521:orcl MySQL: com.mysql.jdbc.Driver
jdbc:mysql://localhost:3306/test
Ejemplo: Crear conexión
try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");} catch (ClassNotFoundException e) {
// mensaje de error}}
Connection con = DriverManager.getConnection("jdbc:odbc:myDataSource", "admin", "pwd");
try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");} catch (ClassNotFoundException e) {
// mensaje de error}}
Connection con = DriverManager.getConnection("jdbc:odbc:myDataSource", "admin", "pwd");
Metadatos DatabaseMetaData
Se obtiene de la conexión Devuelve información acerca de la estructura de la
base de datos DatabaseMetadata dmd = con.getMetaData(); ResultSet tablas = dmd.getTables(……);
ResultSetMetaData Se obtiene de un objeto ResultSet Devuelve información sobre las columnas que
forman el ResultSet ResultSet rs = stmt.executeQuery(sqlString); ResultSetMetaData rsmd = rs.getMetaData(); int colType[] = new int[rsmd.getColumnCount()];
Statement Para ejecutar consultas o modificaciones sobre
la BD, hay que crear antes un objeto Statement
Se utiliza el método createStatement() de la conexión
Una instancia de Statement se puede reutilizar para realizar varias operaciones
Para realizar una consulta, se utiliza el método
executeQuery(sentenciaSQL) Devuelve un objeto ResultSet Si se obtienen varios conjuntos de datos, se puede
pasar al siguiente con getMoreResults() Para realizar una modificación (o cualquier
operación que no devuelva datos), se utiliza el método executeUpdate(sentenciaSQL)
Devuelve el número de filas afectadas
Ejemplo: Statement
Statement st = con.createStatement();ResultSet rs = st.executeQuery(
"SELECT * FROM PRODUCTS");st.executeUpdate(
"UPDATE PRODUCTS SET NAME='CocaCola' " + "WHERE PRODUCTID=1");
Statement st = con.createStatement();ResultSet rs = st.executeQuery(
"SELECT * FROM PRODUCTS");st.executeUpdate(
"UPDATE PRODUCTS SET NAME='CocaCola' " + "WHERE PRODUCTID=1");
Método execute El método execute(sql) permite
ejecutar un Statement cuando no se sabe si contiene una consulta o una sentencia de actualización Devuelve true si es una consulta Devuelve false si es una actualización
El método getResultSet() devuelve el conjunto de resultados obtenido Si no es una consulta, devuelve null
El método getUpdateCount() devuelve el número de registros actualizados
ResultSet El resultado de una consulta es un objeto
ResultSet next() permite pasar a la siguiente fila
devuelve true si ha podido leer la fila getInt(..), getString(..), etc. devuelven el
valor de una columna Se pueden obtener por posición o por nombre
(las posiciones empiezan en 1) rs.getInt(1) o rs.getInt("ID")
close() cierra el ResultSet El ResultSet de JDBC 1.2 sólo permite avanzar
por las filas hacia delante y leer las columnas de izquierda a derecha una sola vez
Ejemplo: ResultSet
Statement st = con.createStatement();ResultSet rs = st.executeQuery(
"SELECT * FROM PRODUCTS");while (rs.next()) {
System.out.print("ID: ");System.out.println(rs.getInt(0));System.out.print("Nombre: ");System.out.println(rs.getString(1));System.out.println();
}rs.close();
Statement st = con.createStatement();ResultSet rs = st.executeQuery(
"SELECT * FROM PRODUCTS");while (rs.next()) {
System.out.print("ID: ");System.out.println(rs.getInt(0));System.out.print("Nombre: ");System.out.println(rs.getString(1));System.out.println();
}rs.close();
JOINS No todos los gestores de BD realizan
igual las combinaciones de tablas (joins) JDBC proporciona una sintaxis especial
que el driver se encarga de traducir SELECT d.name AS Departamento, e.* FROM {oj dept d left outer join emp e on d.deptno=e.deptno}
PreparedStatement Si se va a lanzar la misma operación varias
veces con distintos parámetros se puede optimizar utilizando PreparedStatement (deriva de Statement)
La sentencia se precompila y es más eficiente Los objetos PreparedStatement se crean con el
método prepareStatement(sql) de la conexión
Los parámetros se indican en la SQL con ? Los valores de los parámetros se establecen
con los métodos setInt, setString, etc. Reciben la posición del parámetro y el valor que
toma La posición empieza en 1
Ejemplo: PreparedStatement
PreparedStatement ps = con.prepareStatement("SELECT * from Autor " + "WHERE ID=?");
ps.setInt(1,1);ResultSet rs = ps.executeQuery();
PreparedStatement ps = con.prepareStatement("SELECT * from Autor " + "WHERE ID=?");
ps.setInt(1,1);ResultSet rs = ps.executeQuery();
CallableStatement Se utiliza para llamar a procedimientos
almacenados Se crean con el método prepareCall(sql) La SQL tiene la estructura:"{call nombre_proc(?,?)}"
Parámetros Entrada: como en PreparedStatement Salida: se deben registrar antes de la ejecución con
el método registerOutParameter(pos,tipo) Se ejecuta llamando al método execute() El resultado se obtiene llamando al método getResultSet()
Ejemplo: PreparedStatement
CallableStatement cs = con.prepareCall("{call InsertarEmpleado(?,?,?)}");
String nombre = "José García";int edad = 43cs.setString(1,nombre);cs.setInt(2,edad);cs.registerOutParameter(3,java.sql.Types.INTEGER);ResultSet rs = ps.executeQuery();while (rs.next()) {
System.out.println("Insertado empleado: " + rs.getString(1) + " - " + rs.getString(2));
}int id = cs.getInt(3);
CallableStatement cs = con.prepareCall("{call InsertarEmpleado(?,?,?)}");
String nombre = "José García";int edad = 43cs.setString(1,nombre);cs.setInt(2,edad);cs.registerOutParameter(3,java.sql.Types.INTEGER);ResultSet rs = ps.executeQuery();while (rs.next()) {
System.out.println("Insertado empleado: " + rs.getString(1) + " - " + rs.getString(2));
}int id = cs.getInt(3);
Transacciones Por defecto, las conexiones funcionan
en modo autocommit Cada operación conlleva su propia
transacción Si se deshabilita autocommit
(setAutoCommit(false)), las transacciones se controlan manualmente Se inician al ejecutar cualquier Statement commit() acepta la transacción rollback() descarta la transacción
Concurrencia de transacciones Cuando se ejecutan a la vez distintas
transacciones se pueden presentar los siguientes problemas Lecturas sucias: Se leen datos insertados
por otras transacciones que aún no se han confirmado
Lecturas no repetibles: Se lee la misma fila dos veces seguidas y se obtienen datos distintos (modificaciones de otras transacciones)
Lecturas fantasma: Se leen varias filas que cumplen cierto criterio dos veces seguidas y se obtienen filas distintas (inserciones o borrados de otras transacciones)
Niveles de aislamiento Se especifican en el método setTransactionIsolation(...)
Connection.TRANSACTION_NONE No utiliza transacciones
Connection.TRANSACTION_READ_UNCOMMITED
Permite lecturas sucias, no repetibles y fantasma Connection.TRANSACTION_READ_COMMITED
Permite lecturas no repetibles y lecturas fantasma Connection.TRANSACTION_REPEATABLE_READ
Permite sólo lecturas fantasma Connection.TRANSACTION_SERIALIZABLE
Se asegura la consistencia de todas las lecturas
JDBC 2.0 Mejoras en ResultSet
ResultSet desplazables ResultSet actualizables
Actualizaciones en lote Tipos de datos avanzados Optimización de conexiones (pooling) Uso de JNDI (Java Naming and Directory
Interface) para localizar bases de datos Conjuntos de datos con soporte JavaBean
(RowSet) Transacciones distribuidas
(JTS: Java Transaction Services)
Mejoras en ResultSet createStatement(SCROLLTYPE,UPDATETYPE)
SCROLLTYPE Resultset.TYPE_FORWARD_ONLY
Desplazamiento sólo hacia adelante Resultset.TYPE_SCROLL_INSENSITIVE
Permite desplazamiento, pero no ve cambios realizados por otros
Resultset.TYPE_SCROLL_SENSITIVE Permite desplazamiento y ve los cambios
UPDATETYPE Resultset.CONCUR_READ_ONLY:
Sólo lectura Resultset.CONCUR_UPDATABLE
Permite modificar los datos
Desplazamiento por ResultSet void afterlast();
Se desplaza a la posición siguiente de la última fila
boolean isAfterLast(); Indica si está posicionado
después de la última fila void beforefirst();
Se desplaza a la posición anterior a la primera fila
boolean isBeforeFirst(); Indica si está posicionado
antes de la primera fila boolean first();
Se posiciona en la primera fila boolean isFirst();
Indica si está en la primera fila
boolean last(); Se posiciona en la última fila
boolean isLast(); Indica si está en la última
fila boolean next();
Se mueve a la siguiente fila boolean previous();
Se mueve a la fila anterior boolean relative(int n);
Se mueve n filas desde la fila actual
boolean absolute(int n); Se posiciona en la fila nº n
ResultSet actualizables Actualización de filas
Los métodos updateInt(col,valor), updateString(col,valor), etc. modifican una columna de la fila actual con el valor indicado
El método updateRow() almacena los cambios en la BD
Si se desplaza el ResultSet antes de llamar a updateRow() se pierden los cambios
El método cancelRowUpdates() restaura los valores originales de la fila
ResultSet actualizables
Inserción de filas Desplazarse a la "fila de inserción"
con el método moveToInsertRow() Introducir los datos con los métodos updateXXX()
Guardar la fila con insertRow() Borrado de filas
Se utiliza el método deleteRow()
Actualizaciones en lote Se deshabilita autocommit
con.setAutoCommit(false); Se contruye un Statement
Statement st = con.createStatement ();
Se añaden sentencias al Statement st.addBatch("...")
Se envían las sentencias a la BD int[] rowCounts = st.updateBatch();
Devuelve un array con el número de filas afectadas por cada sentencia del lote
Tipos de datos avanzados
DISTINCT STRUCT ARRAY BLOB CLOB REF
JDBC 3.0
SavePoints (transacciones parciales)
Pool de PreparedStatement Recuperación de claves
autogeneradas Soporte de cursor Hold Posibilidad de mantener varios
ResultSet abiertos a la vez
SavePoints Permite deshacer parcialmente una
transacción:Statement stmt = con.createStatement();
stmt.executeUpdate("INSERT INTO TAB1(COL1) VALUES ('PRIMERO')");
Savepoint svpt1 = con.setSavepoint("SAVEPOINT_1");
stmt.executeUpdate("INSERT INTO TAB1 (COL1) VALUES ('SEGUNDO')");
con.rollback(svpt1);
con.commit();
Statement stmt = con.createStatement();
stmt.executeUpdate("INSERT INTO TAB1(COL1) VALUES ('PRIMERO')");
Savepoint svpt1 = con.setSavepoint("SAVEPOINT_1");
stmt.executeUpdate("INSERT INTO TAB1 (COL1) VALUES ('SEGUNDO')");
con.rollback(svpt1);
con.commit();
Obtener claves generadas Indicar en executeUpdate el parámetro Statement.RETURN_GENERATED_KEYS
Ejecutar getGeneratedKeys() para obtener un ResultSet con las claves generadas
Statement stmt = conn.createStatement();stmt.executeUpdate(
"INSERT INTO ORDERS (...) VALUES (...)", Statement.RETURN_GENERATED_KEYS );
ResultSet rs = stmt.getGeneratedKeys();if (rs.next()) { int clave = rs.getInt(1);}
Statement stmt = conn.createStatement();stmt.executeUpdate(
"INSERT INTO ORDERS (...) VALUES (...)", Statement.RETURN_GENERATED_KEYS );
ResultSet rs = stmt.getGeneratedKeys();if (rs.next()) { int clave = rs.getInt(1);}
En Internet: http://java.sun.com
Página oficial de Sun (inglés) Documentación API J2SE
http://java.sun.com/j2se/1.5.0/docs/api/index.html
Libros: "Piensa en Java"
Bruce Eckel - Pearson Educación
Enlaces y Bibliografía