miércoles, 28 de mayo de 2008

Clave STATIC

En la declaración de una variable miembro se puede indicar que la variable es una variable miembro de la clase.

class UnEnteroLlamadoX {
static int x;
public int x() {
return x;
}
public void setX(int newX) {
x = newX;
}
}

También se emplea static para especificar que un método es un método de clase en vez de un método de ejemplar. Estos métodos sólo pueden operar con variables de clase y no pueden acceder a las variables de ejemplar definidas en la clase:

class UnEnteroLlamadoX {
private int x;
static public int x() {
return x;
}
static public void setX(int newX) {
x = newX;
}
}

Apache Commons-logging

Nos descargamos las librerías commons-logging y apache-log4j, y las vinculamos al proyecto "eticom.ui". Está enfocada para imprimir en consola mensajes, unos sí y otros no, a distintos niveles (warnings, avisos, niveles de errores, etc.). Si tenemos varios proyectos, podemos hacer distinción del tipo de mensaje y las herramientas a utilizar de cada uno de ellos.

La primera de las librerías nos permite acceder al objeto. Vamos a sustituir un comando "System.out.println("");" por un objeto logger de la clase Log:
Log logger = LogFactory.getLog(getClass());

...así cuando queramos mandar un mensaje a consola mientras se ejecuta nuestro código:
logger.info("registro usuario");
logger.debug("intentando conectar Blogger");



La segunda librería nos da otro mensaje y les da formato a los mismos (que aparecen en el archivo
log4j.xml.

Existen varias categorías de mensajes (ordenados de mayor prioridad a menor): ERROR, INFO, WARN, DEBUG. Si digo que quiero ver los mensajes ERROR, se verán sólo del mensajes ERROR, si digo INFO, se verán los INFO y los ERROR, y así sucesivamente. Estos mensajes se indican en el archivo src/log4j.xml (pestaña source).

En definitiva, esta aplicación sirve para seleccionar la información (a través de mensajes) que queramos que nos aparezca en consola, para que así, en proyectos importantes, la consola no quede inundada por toda la información, sino sólo que queramos.

Ejemplo: el log se define en una clase (MiVentana.java), y al correr la aplicación (VentanaBlog.java) vemos como en la consola aparece la información del log definido en la primera clase.

Información del foro de clase

martes, 27 de mayo de 2008

Jerarquía de Componentes y Eventos

MODELO DE EVENTOS

Se basa en que los objetos sobre los que se producen los eventos (event sources) registran los objetos que deberán gestionarlos (event listeners), para lo que los listeners necesitan de los métodos adecuados, y estos se implementan de las interfaces Listener, que se corresponden con los tipos de eventos que se pueden producir.

El proceso que hay que seguir para crear una aplicación orientada a eventos con interface gráfica de usuario:
  1. Saber los componentes que formarán parte de la interface de usuario.
  2. Crear una clase para la aplicación, que debe contener la función main().
  3. Crear una clase Ventana que extienda de Frame y que responda al evento WindowClosing().
  4. a función main() debe crear un objeto de la clase Ventana, donde introduciré los componentes y que mostrarépor pantalla.
  5. Añadir al objeto Ventana los componentes y menús que desee (se puede hacer desde la función main() o desde el constructor de la ventana.
  6. Definir los objetos Listener (que se encargarán de responder a los eventos y cuyas clases implementan las distintas interfaces Listener) para cada uno de los eventos que deban estar soportados.
  7. Implementar los métodos de las interfaces Listener que se vayan a hacer cargo de la gestión de los eventos.
Jerarquía de Eventos
La superclase EventObject pertenece al paquete java.util, y deriva la clase AWTEvent, de la que dependen todos los eventos de AWT. Los eventos de Java se encuentran agrupadas en el paquete java.awt.event, y se pueden agrupar en:
  • Eventos de alto nivel: llamados así porque la acción de la que derivan tiene un significado en sí misma, son los que tienen que ver con clicar botones o elegir comandos (ActionEvent), cambiar valores en barras de desplazamiento (AdjustmentEvent), elegir valores (ItemEvents) y cambiar el texto (TextEvent).
  • Eventos de bajo nivel: son las acciones elementales que hacen posible los eventos de alto nivel y que se producen con las operaciones elementales con componentes (ComponentEvent), con los containers (ContainerEvent), con pulsar teclas (KeyEvent), con todo lo que tenga que ver con el uso del ratón (MouseEvent), con obtener o perder el focus (FocusEvent) y con las operaciones con ventanas (WindowEvent).
La siguiente tabla muestra los componentes del AWT y los eventos específicos de cada uno de ellos:



Y esta otra tabla muestra los componentes del AWT y todos los tipos de eventos que se pueden producir sobre cada uno de ellos (tener en cuenta que también son específicos de sus superclases):





AWT (Abstract Window Toolkit)


Las Java Foundation Classes (JFC en español) son un framework gráfico que sirven para construir interfaces gráficas de usuario basadas en Java. Está compuesta de AWT (Abstract Window Toolkit), Swing y Java 2D, y recrean una interfaz de usuario para programas Java. En definitiva, son las API estándar para suministrar una interfaz gráfica de usuario (GUI) para un programa Java.

AWT (Kit de herramientas de Ventana Abstracta -en español-), es un kit de herramientas de gráficos, interfaz de usuario, y sistema de ventanas independiente de la plataforma original de Java. Llegados a J2SE 1.2, los widgets de AWT fueron superados a los del kit Swing, que es una biblioteca gráfica para Java que forma parte de las JFC y que incluye widgets para interfaz gráfica de usuario tales como cajas de texto, botones, desplegables y tablas.

________________________

En resumen, AWT se encuentra en el paquete java.awt y se apoya en la plataforma para la visualización, lo que provoca cambios según la plataforma que empleamos; Swing es una extensión de AWT.

Vamos a realizar nuestra primera ventanuca: ejemploFrame.java

La estructura del AWT se resume en que los Contenedores (Containers) contienen Componentes (Components), que son los controles básicos, los que a su vez contienen Objects; no se usan posiciones fijas de los Componentes, sino que están situados a través de Layouts; no existe un formato de recursos por lo que no se puede separar el código de la interface (no hay ningún diseñador de interfaces).

La interface gráfica se compone de elementos gráficos básicos de usuario:
  • Los contenedores (container): es la ventana o parte de la ventana donde se colocarán los componentes y donde se realizan los dibujos. Los contenedores contienen y organizan la situación de los Componentes. Los contenedores son en sí mismo contenedores, por lo que pueden ir dentro de ellos mismos. En el AWT, todos los contenedores son instancias de la clase Container o uno de sus tipos.
  • Los componentes (componet):botones, barras de desplazamiento, etiquetas, listas, cajas, campos de texto, etc., que permiten al usuario interactuar con la aplicación y proporcionar información desde el programa al usuario sobre el estado del programa. En AWT, todos los componentes de la interface de usuario son instancias de la clase Component. Los componentes se agrupan dentro de contenedores.


    Algunas de las características de los componentes:
    1. Todos los Components (menos Window y sus derivados) se tienen que añadir a un Container.
    2. Para añadir un Component a un Container se emplea el método add() de la clase Container: ventana.add(boton);
    3. Los Containers de máximo nivel son las Windows (Frames y Dialogs). Los Panels y ScrollPanes siempre deben estar de otro Container.
    4. Un Component sólo puede estar dentro de un Container. Si esta en uno y se añade a otro, deja de estar en el primero.
    5. La clase Component tiene variables y métodos básicos, que son heredados por todas sus sub-clases.
  • El modelo de eventos: el usuario controla la aplicación actuando sobre los componentes (con el ratón o el teclado). Cada vez que el usuario realiza una acción, se produce el evento correspondiente, y que el sistema operativo transmite al AWT, el cual crea un objeto de una determinada clase de evento, derivada de AWTEvent. Este evento es transmitido a un determinado método para que los gestione. En definitiva, el objeto o componente que recibe el evento debe registrar o indicar previamente qué objeto se va a hacer cargo de gestionar ese evento. Jerarquía de eventos:

Basándonos en las clases MiVentana, MiBoton y MiTexArea que están en el repositorio, he creado mi clase Ventana.java.

Archivos .JAR y Suite de pruebas

Un archivo .JAR (Java ARchive) es un conjunto de clases que se encuentran agrupadas y que además permite ejecutar aplicaciones escritas en JAVA.

Vamos a emplearlo en nuestro proyecto eticom-blogger, de tal forma que lo generamos a través de la ruta en eclipse: File/Export/Java/Jar File. Hay que seleccionar los 'resources' a incluir (src) y depués selccionamos el destino a exportar (nombre y dir del .jar): 'Select the export destination'.

Suite de pruebas
Es un conjunto de clases de pruebas que se lanzan (se lanza la suite) de forma secuencial, cada una de las cuales tiene sus métodos de pruebas. Para lanzarlas: menú contextual sobre la suite.xml que está en la carpeta test del proyecto/Run as/Suite.

Al haber generado nuestro .JAR, podemos prescindir de la libreria que teníamos y añadir nuestro .JAR (que tiene todas las librerías que necesitamos para nuestro proyecto eticom-blogger).

viernes, 23 de mayo de 2008

Diferencias entre las colecciones List, Set y Map


Las colecciones son objetos que contienen objetos y que se usan para almacenar, obtener, manipular y comunicar datos incluidos en éstas. Normalmente, los objetos incluídos en ellas suelen ser del mismo tipo, aunque no necesariamente, depende de si son o no genéricas.

Las colecciones se diferencian de los arrays en que su tamaño no es fijo, esto es, son dinámicas. Se pueden realizar operaciones de incluir, eliminar, obtener, encontrar o recorrer una colección.

La Java Collections Framework (JCF) está constituída por sus interfaces (las más importantes List, Set y Map), interfaces de soporte (Iterator, ListIterator, Comparable y Comparator) y de clases de distintos usos, es decir, las implementaciones de las interfaces, y que sirven para
almacenar y manipular grupos de datos como una sola unidad, como una colección (HashSet, TreeSet, ArrayList, LinkedList, HashMap, TreeMap, etc.). También hay clases abstractas que tienen total o parcialmente implementados los métodos de la interface correspondiente, y que sirven para que los usuarios deriven de ellas sus propias clases de forma más sencilla.

Dos clases que implementan la misma interface se pueden utilizar exactamente de la misma forma, aunque difieran en cuanto a la implementación y, por tanto, su eficiencia.

Interfaces Comparable y Comparator
Sirven para mantener ordenadas las listas, así como los sets y los maps que deban mantener un orden.
Comparable declara el método compareTo() que compara su argumento implícito por el que se le pasa por parámetro, devolviendo -1, 0 ó 1 según el argumento sea anterior, igual o posterior al objeto o:
public int compareTo(Object o);

Comparatorpermite ordenar listas y colecciones cuyos objetos pertenecen a clases de cualquier tipo. La idea es parecida a la de Comparable, pero el usuario debe proporcionar la implementación de la interface. Esta interface declara los métodos equals(), que compara dos Comparators, y compare(), que devuelve -1, 0 ó 1 según el argumento sea anterior, igual o posterior al segundo:
public boolean equals(Object o);
public int compare(Object o1, Object o2);
______________________

Vamos a analizar las interfaces mmás importantes de la JCF:

INTERFACE LIST
Se encarga de definir métodos para trabajar con colacciones ordenadas y con elementos repetidos. Algunos de los
métodos de la interface List son los siguientes:
  • add(Object o): añade un objeto al final de la lista.
  • add(int indice, Object o): añade un objeto a la lista en la posición indicada.
  • get(int indice): devuelve el objeto de la lista de la posición indicada.
  • remove(int indice): elimina el objeto de la lista pasado por parámetro.
  • clear(): elimina todos los elementos de la lista.
  • indexOf(Object o): devuelve la posición de la primera vez que un elemento coincida con el objeto pasado por parámetro. Si el elemento no se encuentra devuelve -1.
  • lastIndexOf(Object o):devuelve la posición de la última vez que un elemento coincida con el objeto pasado por parámetro. Si el elemento no se encuentra devuelve -1.
  • size(): devuelve el número de elementos de la lista.
  • contains(Object o): devuelve verdadero si en la lista aparece el objeto pasado por parámetro, para lo cual utiliza intrínsecamente el método equals().
Existen implementaciones de la interface List, como son las clases ArrayList y LinkedList. Hay otras dos que no voy a comentar: Vector(h) y Stack(h).

ArrayList
se basa en índices, siendo cero la posición inicial e infinito su posición final, o lo que es lo mismo, contiene tantos objetos como necesitemos, almacenando los elementos en un array de objetos. Esta clase tiene varios constructores, siendo la más importante el ArrayList(), que construye un ArrayList con capacidad cero por defecto pero con infinitos objectos a insertar. Si le queremos dar un tamaño empleamos el constructor
ArrayList(int numElementos). ArrayList implementa la interfaz List y extiende de la clase abstracta AbstractList.

LinkedList almacena los elementos en una lista vinculada y permiten un acceso a ella de manera secuencial, pero su uso no es tan eficiente como los arrays.

INTERFACES
SET<E> y SORTEDSET<E>
Sirve para acceder a una colección sin elementos repetidos (hay que saber cuándo dos objetos son considerados iguales; para ello se usan equals() y hashcode();). Puede estar o no ordenada, y no declara ningún método adicional a los de Collection. Algunos de l
os métodos de la interface Set son los siguientes:
  • add(Object o): añade el objeto pasado por parámetro al Set siempre que éste no exista ya, y devuelve un booleano.
  • clear(): Elimina a todos los elementos del Set.
  • contains(Object o): devuelve true si el Set contiene el objeto pasado por parámetro. Para ello, se compara de forma interna con el método equals (o.equals(x);) o con el método hashCode().
  • isEmpty(): devuelve true si el Set está vacío.
  • iterator(): devuelve un iterador
  • remove(Object o): elimina el objeto pasado por parámetro si existe y devuelve un booleano.
  • size(): devuelve un entero que es el número de elementos del Set.
La interface SortedSet extiende de la interface Set y añade una serie de métodos, entre los que hay que destacar:
  • comparator(): obtiene el objeto pasado al constructor para establecer el orden; si se emplea el orden natural definido por la interface Comparable, devuelve null;
  • first() / last(): devuelve el primer o el último elemento del conjunto.
Existen dos implementaciones de conjuntos, como son la clase HashSet y la clase TreeSet.

HashSet<Elemento>
Implementa la inteface Set y está basada en una hash table. Hace distinción de identidad, esto es, que sólo pueden existir elementos diferentes (nada de duplicados). No se respeta el orden en el que se insertan los elementos y el tamaño del conjunto se adapta dinámicamente a lo que se necesite. HashSet implementa la interfaz Set y extiende de la clase abstracta AbstractSet.

TreeSet
<Elemento>
Implementa SortedSet y se basa en un TreeMap.

INTERFACES
MAP<Clave, Valor> y SORTEDMAP<Clave, Valor>
Un Map es una estructura de datos agrupados en parejas clave/valor; pueden ser considerados como una tabla de dos columnas. La clave debe ser única y se emplea para acceder al valor.
Map no deriva de Collection, pero sí se pueden ver los Maps como colecciones de claves, de valores o de claves/valores. Algunos de los
métodos de la interface Map son los siguientes:
  • clear(): elimina todos los mapeos del Map.
  • containsKey(Object clave): devuelve true si el Map contiene un mapeo igual que el objeto pasado por parámetro: boolean existe = productos.containsKey(producto);
  • containsValue(Object valor): devuelve true si el Map mapea a uno o más claves del objeto valor pasado por parámetro.
  • get(Object clave): devuelve el objeto valor de la clave pasada por parámetro; o null si el Map no encuentra ningún mapeo con esta clave.
  • isEmpty(): devuelve true si el Map está vacío.
  • put(Clave clave, Valor valor): asigna el valor pasado con la clave especificada a otro objeto valor.
  • remove(Object clave): elimina el mapeo que tenga la clave pasada por parámetro si existe, devolviendo el valor de dicho mapeo.
  • size(): devuelve un entero con el número de mapeos del Map.
La interface SortedMap añade métodos similares a los de SortedSet.

Existen tres implementaciones como son las clases HashMap, HashTable(h) y TreeMap.

HashMap<Clave,Valor>
esta clase mapea claves con valores, pero no permite claves duplicadas porque se solaparía el valor. Tanto la clave como el valor pueden ser cualquier tipo de objeto, y ambos pueden tener el valor null. Esta clase no garantiza el orden de los elementos ni que no puedan cambiar de orden. HashMap implementa la interfaz Map y extiende de la clase abstracta AbstractMap.
Esta clase posee internamente (de la clase AbstractMap) los métodos equals, hashCode y toString.

HashTable<Clave,Valor>
Es una clase que implementa Map y que almacena pares del tipo clave/valor en una tabla de dispersión. Al emplearla se proporciona un objeto que sirve como clave y otro como valor (vinculando el valor a la clave).Su insercion y búsqueda es rápida. Un ejemplo sería un listín de teléfonos, en el que dado un nombre se proporciona un teléfono.

TreeMap<Clave,Valor>
Esta clase implementa SortedMap y se basa en una árbol binario.

TestNG: causas, efectos, consecuencias, beneficios

A través de TestNG se pueden realizar pruebas para comprobar el perfecto funcionamiento de las clases, métodos de clases, etc. que creemos en un proyecto.

Realizando una prueba antes de implementar el código, buscamos que el código de la prueba falle para que, una vez realizada la implementación, si el resultado es positivo, indique que el bloque de código de nuestro proyecto es correcto.

La idea de la prueba es realizarla paso a paso e ir probando para así ir determinando que cada instrucción se está desarrollando de manera correcta.

Una prueba se realiza a través de un método dentro de una clase denominada como la clase que vamos a comprobar (MiClaseTest). El método debe ir precedido de la anotación "@Test" que indica que es un método al que hay que realizar prueba. También se emplean las anotaciones @BeforeTest o @BeforeMethod para inicializar los valores cada vez que realicemos una prueba en cada uno de los métodos; del mismo modo se emplea @AfterTest o @AfterMethod para limpiar los recursos empleados en los métodos de prueba.

Un ejemplo de código sería el siguiente:

public class MiClaseTest{

@BeforeTest
public void inicializarRecursos(){
...
}

@After
public void limpiarRecursos(){
...
}

@Test
pruebaTest(){
...
}

}

Se pueden crear tantos Tests dentro de la clase Test como deseemos. La estructura de estos métodos es la siguiente:
  • El escenario de pruebas, donde se declaran (si no se ha hecho antes en @BeforeTest) los objetos a emplear en el método.
  • La invocación, donde se implementa el objeto declarado en el escenario de pruebas con un método que será definido en la clase.
  • Confirmación de resultados: a través de la instrucción Assert (que contiene una expresión booleana) verificamos que los resultados de la invocación sean verdaderos o falsos.
Ejemplo:

@Test
public void pruebaAddProducto(){

//Escenario de pruebas:
Producto producto = new Producto();

//Invocación:
producto.AddProducto(producto);

//Confirmación de resultados:
assert(producto.productos.size()==1);
assert(ptoducto.productos.contais(producto));
}

Ejemplo completo de clase Test: CarritoCompraTest.java.

Uso (o no) de valores genéricos

Post Relacionado con el de Diferencias entre las colecciones List, Set y Map
Para utilizar una lista, podemos no utilizar genéricos (esto es, no definir el tipo de objetos que debe contener la lista):

List lista = new ArrayList();

...y para añadir:

lista.add(new Alumno()); //añadimos un tipo Alumno
lista.add(new String()); // añadimos un tipo String

...si queremos saber el valor de la posición cero:

Object o = lista.get(0);
Alumno al = (Alumno)o;

Si utilizamos con genéricos:

List<Alumno> lista = new ArrayList<Alumno>();

donde sólo podremos incluir y obtener objetos de tipo Alumno. Con lo que ante la instrucción de incluir un objeto de tipo String en esta lista nos daría un error de compilación:

lista.add(new String); //nos daría error
lista.add(alumno2); //sería correcto

...tampoco habría que hacer un casting si queremos obtener un determinado objeto de la lista:

Alumno al = lista.get(0);

_______________________

Si queremos recorrer una lista genérica, se puede hacer con un bucle for:

for(int i=0;i
Object o = lista.get(i);
System.out.println(o);
}

...o bien a través de un for each:

for each(Alumno al: lista){
System.out(al.getNombre());
}

________________________

También se puede emplear, en lugar de List, el comando Set:

miércoles, 21 de mayo de 2008

POO (Programación Orientada a Objetos)

El lenguaje orientado a objeto facilita a los programadores la posibilidad de cambiar el código de un programa, así como reutilizarlo, sin que repercuta en el resto del mismo. Esto también afecta positivamente al cliente que quiera modificar algo.
En definitiva, la POO nos permite hacer los programas y módulos más fáciles de escribir, mantener y reutilizar.

Cuando creamos una clase, no trabajamos con ellas, sino que nos da la posibilidad de trabajar con objetos de dicha clase para así poder realizar tareas:

MiClase o = new MiClase();

Los objetivos de la POO son:
  • La posibilidad de reutilizar los códigos
  • Extensibilidad del código:
  • Modularidad del código: es la separación a través de p.e. paquetes dependiendo de su funcionalidad. Es una parte complicada de realizar.
  • Código robusto.
  • Código mantenible: que se pueda restablecer, en un momento dado, en un tiempo razonable.
Como he dicho, el trabajo lo realizan los objetos (dentro de un escenario de pruebas). Los objetos son entidades que combinan estado (son los atributos a los que se le asignan valores concretos: sus propiedades), comportamiento (está relacionado con lo que sus métodos pueden hacer, es decir, qué operaciones se pueden realizar con él) e identidad (es la propiedad que lo diferencia de los demás: su identificador).

¿Qué sabe hacer un objeto?


Teniendo como clase Producto y atributos 'stock' y 'nombre', existen dos métodos; una que sirve para cambiar el estado de nuestro objeto (método setter):

public void setStock(int x){
this.stock = x;
}

...y otra que sirve para hablar de sí misma mostrando su estado (método getter):

public int getStock(){
return stock;
}

...por último se pueden gestionar procesos (intercambio de mensajes): emplear vocabulario "envía mensaje",...

¿A quién conoce un objeto? ¿Con quién se puede comunicar?



¿Quién es el objeto y cuál es su estado? Identidad y estado



Un objeto/clase se relaciona con otros objetos/clases para así poder hacer su trabajo



Relaciones en el modelado/diseño orientado a objetos



Características de la POO
  • Abstracción:
  • Encapsulamiento:
  • Polimorfismo:
  • Herencia:

Principios de diseño de la Programación Orientado a Objetos
  • Principio de la única responsabilidad:
  • Principio abierto-cerrado:
  • Principio de substitución de liskov:
  • Principio de inversión de dependencia:
  • Principio de segregación de la interfaz:

martes, 20 de mayo de 2008

Excepciones

Para poder lanzar una excepción, hay que extender la clase java.lang.Exception, la cual deriva de la clase Throwable; su jerarquía de clases es la siguiente:

Dentro de la clase Exception se pueden distinguir, la clase RuntimeException, relacionada con errores de programación (excepciones implícitas), y el resto de clases derivadas de Exception (excepciones explícitas) que Java obliga a tratar si se producen.

Son las excepciones implícitas las que se emplean para la detección de errores y que ocurren durante la ejecución del programa que interrumpe el flujo normal de las sentencias y lanza un throw (excepción) que nosotros debemos capturar mediante un catch y así solucionar el error. Se producen por lo general durante la ejecución,aunque lo suyo sería que sucediera durante la compilación.

Ejemplo de bloque try/catch:




Hay veces en los que el código de un método puede generar una excepción y no se desea incluir en ese método la gestión del error. Para estos casos Java permite que el método pase o relance la excepción al método desde el que ha sido llamado, sin incluir en el método los bucles try/catch; esto se consigue con la inclusión de la pablabra throws más el nombre de la Excepción, después de la lista de argumentos del método. Aun así, en el método superior habría que incluir los bloques try/catch o volver a pasar la excepción:

void método2() throws IOException, MyException {
   ...
   //código que puede lanzar las excepciones IOException y MyException
   ...
}//Fin del método

Ejemplo de intento de conexión a un blog empleando una excepción en el caso que el acceso mediante coreeo electrónico y clase no fuese correcto: ConectionTest.java

viernes, 16 de mayo de 2008

Métodos 'contains()' y 'sort()'

Relacionado con las colecciones tenemos las repercusiones de equals en el método contains y la forma de ordenar una colección con 'sort()' empleando 'Collections.sort(List l)':

public class PersonaTest {
List personas;
Persona persona1,persona2, persona3;
@BeforeTest
public void inicializarRecursos(){
personas=new ArrayList();

persona1=new Persona();
persona1.nombre="juan";
persona2=new Persona();
persona2.nombre="juan";
persona3=new Persona();
persona3.nombre="pepe";
}
@AfterTest
public void limpiarRecursos(){
persona1=null;
persona2=null;
persona3=null;
personas=null;
}
/**
* dos personas son iguales si sus nombres son iguales
*/
@Test
public void pruebaEqualsEnFuncionAtributoNombre(){
assert(persona1.equals(persona2));
assert(!persona1.equals(persona3));

}

@Test
public void pruebaContains(){
assert(!personas.contains(persona1));
personas.add(persona1);
assert(personas.contains(persona1));
assert(personas.contains(persona2));
assert(personas.size()==1);
}

@Test
public void pruebaOrden(){
personas.add(persona3);
personas.add(persona1);
Collections.sort(personas);
assert(personas.get(0).equals(persona1));
}

}

@BeforeTest y @AfterTest

De entre las etiquetas de TestNG tenemos:
  • @BeforeTest: antes de que se ejecute el/los métodos de prueba que están en una clase test, que se ejecute el método inferior, tantas veces como @Test haya.
  • @AfterTest: lo mismo que antes pero se hará después de cada método precedido por @Test.
Alumno alum;

@Before test
public void inicializarRecursos(){
alum = new Alumno();
}

@AfterTest
public void limpiarRecursos(){
alum=null;
}

@Test
public void prueba(){
alumno...
}

jueves, 15 de mayo de 2008

Primer proyecto (completo)

Vamos a crear un proyecto desde cero

Lo voy a llamar 'prouno'. En la ventana 'package' menú contextual/new java project/next/finish.

El proyecto tiene que tener tres carpetas tipo Source Folder, una llamada src, otra llamada test y una tercera llamada Lib, ésta de tipo Folder, donde vamos a incluir las librerias, en este caso metemos la libreria testng: la copiamos de otro proyecto y después, menú contextual en la librería/build path/add to build path. Va a parecer que no está en la carpeta lib, pero si lo miramos desde la ventana Navigator veremos que sí.

Ahora vamos a relacionar el proyecto con nuestro repositorio: menú contextual en nuestro proyecto/Team/share project/SVN/next/seleccionamos nuestro repositorio/next/next/finish. Esperamos un rato a que importe los datos. Se abre una ventana que nos pide que seleccionemos lo que queremos importar. Seleccionamos todo menos los .classpath y los .project, y damos a OK... y esperamos un poco. Ya tenemos nuestro proyecto en nuestro repositorio.

Tener en cuenta que las carpetas src y test deben tener una estructura de directorios idéntica a medida que trabajemos con ellas.

En la carpeta src vamos a crear un nuevo package: menú contextual/new/package. Lo llamo eticom. Finish.
Aquí creo una serie de cosas:
  • una clase cualquiera: menú contextual sobre src/eticom, new/class. La voy a llamar 'Coche'. y como atributos: color, marca, puertas.
public class Coche {

//Atributos:
String color;
String marca;
String puertas;

}

  • una clase de tipo enum: creo antes, en src el 'package' eticom.enums. Aquí creo la clase: menú contextual sobre este paquete/new/enum. La llamo 'Nombres', que van a ser los nombres de los posibles nombres de los programadores.
package eticom.enums;

public enum Nombres {
Alberto, Rafa, Antonio
}

  • una anotacion cualquiera con al menos un atributo de tipo primitivo y otro del tipo enum anteriormente creado: al igual que con el paquete enums, creamos un nuevo paquete en src, que la vamos a llamar eticom.anotaciones, y ahí creamos la anotación: menú contextual/new/annotation. La voy a llamar 'Programador', en la que como atributo voy a tener la variable 'nombreProgramador()'. Hay que tener muy en cuenta las importaciones de paquetes.
package eticom.anotaciones;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import eticom.enums.Nombres;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})

public @interface Programador {

//Atributo primitivo:
String cargo();

//Atributo de tipo enum:
Nombres nombreProgramador();

}

  • aplicamos la anotación a la clase que hemos creado, eligiendo los valores correspondientes; la clase quedaría de tal forma:
package eticom;

import eticom.anotaciones.Programador;
import eticom.enums.*;

@Programador(cargo = "jefe de proyecto", nombreProgramador = Nombres.Rafa)

public class Coche {

/*
* Estos son los atributos de la clase
*/

String color;
String marca;
int puertas;

/*
* Método constructor por defecto
*/
public Coche(){
}

/*
* Método constructor
*/
public Coche(String col){
this.color=col;
}

/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/

public boolean equals(Object o){

boolean bol = false;
Coche car = (Coche)o;
if(car.color.equals(this.color)){
bol = true;
}

return bol;
}

}

En la carperta test hay que crear lo siguiente:
Una clase de prueba llamada igual que la clase pero con el sufijo Test en la que creamos:
  • un método de prueba utilizando el framework de pruebas TestNG. En dicho método comprobaremos que los valores de la anotación coinciden con los que esperamos
  • otro método de prueba que compruebe que el método equals de mi clase "Mesa" funciona correctamente. Para ello, en dicho método necesitaremos al menos 3 instancias/objetos de dicha clase para la demostración
package eticom;

import org.testng.annotations.Test;
import eticom.anotaciones.Programador;
import eticom.enums.Nombres;

public class CocheTest {

@Test
public void pruebaProgramador() {

assert(Coche.class.isAnnotationPresent(Programador.class)) : " la anotacion Programador aparece en la clase Coche";
Programador miAnotacion = Coche.class.getAnnotation(Programador.class);
assert(miAnotacion.nombreProgramador().equals(Nombres.Rafa)) : " El valor del nombre no es Alberto ni Antonio";
assert(!miAnotacion.cargo().equals("programador")) : " el cargo es de jefe de proyecto";

}

public void pruebaCoche(){

Coche coche1 = new Coche();
coche1.color = "rojo";
Coche coche2 = new Coche();
coche2.color = "rojo";
Coche coche3 = new Coche();
coche3.color = "negro";

assert(coche1.equals(coche2)): " el " + coche1 + " y el " + coche2 + " deben ser iguales";
assert(!coche2.equals(coche3)): " el " + coche2 + " y el " + coche3 + " deben ser distintos";
}

}

Ahora, al lanzar la clase CocheTest (menú contextual sobre esta clase/Run as/TestNG Test), la prueba tiene que salir en verde, lo que significa que está bien hecho.

NOTA IMPORTANTE: Para estar seguros que está bien, primero hacemos la prueba de CocheTest pero anulando el método public boolean equals(Object o){ } de la clase Coche, para así estar seguros de que hemos hecho bien el casting al objeto y pasado a Coche.

Ahora genero el javadoc (nos genera toda la documentación de nuestro programa), para lo cual seleccionamos, desde la barra menú, proyecto/Generate Javadoc, y en 'Javadoc command' -> C:\Archivos de programa\Java\jdk 1.6.0_06\bin y finish. Y me debería aparecer una nueva carpeta con la documentación, al estilo de las APIs de JAVA.

Ahora actualizo el código de mi proyecto en eclipse al repositorio -> menú contextual sobre mi proyecto/team/commit, selecciono todas las casillas excepto los .classpath y los .project, y pincho en OK.

Y ya hemos completado nuestro primer proyecto empleando una clase, una clase enum, una clase annotation y una clase de prueba.

¿Más claro?

miércoles, 14 de mayo de 2008

Javadoc, Comandos + utilizados, Clases Enum y Colecciones

Hemos visto el Javadoc. Info en la wikipedia.
En eclipse, para que nos salga la documentación en nuestro proyecto. Para ello seleccionamos nuestro proyecto, vamos a Project/Generate Javadoc, y en javadoc command: C:\Archivos de programa\Java\jdk1.6.0_06\bin. Finish.
Ahora ya nos aparece en nuestro proyecto la carpeta Doc.

Comandos más utilizados en desarrollo:

  • Navigate>Open Type
    • ventanita para indicar la clase que queremos editar/ver. Esta ventanita tiene un buscador y funciona la búsqueda por iniciales
  • Navigate>Open Resource
    • lo mismo que la anterior pero nos devuelve como resultado otros tipos de archivos además de las clases java
  • CTRL+SPACE
    • autocompleta
  • CTRL+1
    • sugiere para la correción de error de compilación
  • ALT+MAYS+CURSOR ARRIBA
    • seleccion incremental de código
  • CTRL+MAYS+F
    • Formatear código
  • Refactor>extract local variable
    • seleccionamos el código que representará la futura variable para extraerla/declararla antes
  • Sobreescribir metodos:
    • botón derecho>source>override implemet methods;
__________________

ENUMS

Info en inglés. Ejemplo de Enum (
Prioridad.java):
package eticom.enums;

public enum Prioridad {
alta, media, baja, ninguna

}

Ejemplo aplicado a una anotación (NivelPrioridad.java):
package eticom.anotaciones;

import eticom.enums.Prioridad;

public @interface NivelPrioridad {

Prioridad prioridad();

}

_____________________________

Colecciones de Objetos
Una colección es un objeto contenedor de objetos.
Las colecciones se utilizan para almacenar, obtener, manipular, y comunicar datos incluidos. Los objetos que contiene una colección suelen tener la característica de ser un grupo por su tipo/naturaleza. A diferencia de los arrays, las colecciones son dinámicas, es decir: no tienen un tamaño fijo en tiempo de ejecución.

Las operaciones básicas sobre una colección son:

  • incluir elementos
  • eliminar elementos
  • obtener elementos
  • encontrar elementos
  • recorrer la colección (iterar)

Las implementaciones de Collection en versiones anteriores (1, 2) de Java platform incluyeron Vector, Hashtable, yarray. Pero no se incluía un framework de colecciones, es decir una arquitectura unificada para la representación y manipulación de colecciones.Conteniendo:

  • Interfaces
  • Implementaciones
  • Algoritmos

Tenemos tres interfaces con sus métodos:
- Bailarin: String daVuelta().
- Escalador: String agarraRoca().
- Futbolista: String meteGoles().

public class Persona implements Bailarin,Escalador,Futbolista{
Bailarin b = new Persona();
b.daVuelta();

Escalador e = (Escalador)b;
e.agarraRoca();

Futbolista f = (Futbolista)e;
f.meteGoles();
}


lunes, 12 de mayo de 2008

Anotaciones en Java

Le echamos un vistazo a la web http://groups.google.com/group/eticom-master-java/web/anotaciones. A grnades rasgos podemos decir que son un mecanismo para dotar a las clases de meta-información. Para acceder a la información de una anotación en tiempo de ejecución utilizamos el API de reflexión: java.reflection.
Las anotaciones se emplean para anotar nuestro código, mientras que la información de la anotación puede estar relacionada con la seguridad (permisos, usuarios, roles,...), persistencia (transacciones, cache, tablas, esquemas ...), logging... dando lugar a un nuevo complemento de la POO, la Programación Orientada a Atributos. En definitiva, sirve para explicar el código al código.

Ejemplo anotación:
package eticom.anotaciones;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Desarrollador {

String nombre();

}

Utilización de java.reflection, es decir de la metainformación proporcionada por la clase Class para obtener información sobre las anotaciones existentes de una clase y de su valor: http://code.google.com/p/eticom-master-java/source/browse/trunk/sintaxis/test/eticom/UsuarioTest.java

package eticom;  import org.testng.annotations.Test;  import eticom.anotaciones.Desarrollador;  public class UsuarioTest {    @Test  public void pruebaAnotacionAutorExiste(){   assert(Usuario.class.isAnnotationPresent(Desarrollador.class)):" no existe la anotaci—n";   Desarrollador annotation = Usuario.class.getAnnotation(Desarrollador.class);   assert(annotation.nombre().equals("Juan")):" no coincide el valor con Juan";  }  } 

Pluggin TestNG 5.8 para Eclipse

De nuestros repositorios de google code (http://code.google.com/p/eticom-master-java/downloads/list), descargamos el "testng-5.8.zip" (Test Driven Development) y lo descomprimimos en la carpeta Librerias que creamos en nuestro workspace.

Instalación de plugin para eclipse
  • Select Help / Software updates / Find and Install.
  • Search for new features to install.
  • New remote site.
  • Enter http://beust.com/eclipse in the URL and whatever description you want.
  • Make sure the check box next to http://beust.com/eclipse is checked and click Next.
  • Eclipse will then guide you through the process.

funcionamiento del plugin para eclipse

http://testng.org/doc/eclipse.html

Borro el proyecto que hice "propri" que está en el package (se borra porque hicimos algo mal). Vamos a crear otro:

file/new/project/SVN/Checkout/next
Marcamos "Use existing..." y lo relacionamos con la web
http://eticom-master-java.googlecode.com/svn/trunk/ y damos siguiente. Seleccionamos Sintaxis, que es el proyecto que tiene el profe en la red. Siguiente -> Java/project, le damos un nombre y finish.

Trabajando con eclipse

Vamos a hacer una introducción del eclipse.

Workspace:
Si queremos cambiar el workspace: File/Switch workspace/other.

Views:
Para abrir nuevas ventanas: Window/Show view. Se pueden mover las ventanas a nuestro gusto. Las vistas se pueden cambiar en las preferencias.

Perspectives:
Se pueden generar perspectivas en la pestaña Window. Las vistas disponibles están en la esquina superior derecha, en el botón ">>".

Preferencias del programa: Window/Preferences. Las opciones más interesantes:
  • General/Appearance: por si queremos cambiar los colores de código...
  • General/Content Types: se asocian las preferencias de los distintos tipos de archivos. P.e. los .xml asociados a un .jspx?
  • General/Editors/File Associations: relaciona los archivos con el editor.
  • General/Editors/Text Editors: preferencias del texto del editor.
  • General/Editors/Text Editors/Hyperlinking: para navegar por las clases, propiedades, etc. haciendo click con el ctrl pulsado.
  • General/Editors/Text Editors/Spelling: corrección automática de idiomas.
  • General/Keys: accesos rápidos.
  • General/Workspace: Activamos la casilla "Save automatically before build".
  • Java/Appearance/Members Sort Order: para seleccionar el standard de programación de los tipos (métodos, constructores, etc).
  • Java/Build Path: dirección de la carpeta fuente y destino de un proyecto.
  • Java/Code Style/Code Templates: Aquí podemos cambiar el código generado por defecto y los comentarios de Java.
  • Java/Compiler: se puede ajustar la versión de java que estamos utilizando, para que no haya problemas se compatibilidad.
De momento esto es todo, hay que bichear las opciones que más nos gusten o necesitemos.

viernes, 9 de mayo de 2008

Toma de contacto

Segundo día de curso JAVA (impartido por ETICOM). Aun estableciéndonos.. Hemos instalado el jdk1.6.0_06 (en la consola DOS, para combrobar que se ha instalado bien), ejecutamos 'JAVA', y luego 'java -version' (para conocer nuestra versión).

A continuación creamos nuestra carpeta de trabajo: C:\workspace. Dentro de ella creamos la carpeta 'Librerias'.

Instalamos el Eclipse 3.3 (extraemos el archivo "eclipse-java-europa-winter-win32.zip" en "C:\Archivos de programa\") y nos pedirá que le asignemos un path, y lo hacemos a C:/workspace.
Creamos un nuevo proyecto: "bienvenida" (File/new/java project/next/finish).
Abrimos la pestaña Navigator para ver los proyectos que tenemos en el workspace y todos sus detalles (Window/show view/Navigator).

En el src del proyecto bienvenida (en la pestaña Navigator) creamos una clase (menú contextual sobre src/new/class). En la ventana que se nos presenta tenemos que rellenar lo siguiente:
  • Source: lo dejamos tal cual (bienvenida/src)
  • Package: eticom.jse
  • Name: bienvenida
  • Which Methods: activamos todos.
Ya tenemos la clase creada. Si le añadimos la siguiente linea de código System.out.println("Hola Mundo"); en el bloque public static void main(String[] args) { y clikeamos en el boton verde de play o la ruta "run/run" (compilamos y ejecutamos, con lo que en la carpeta "bin" vemos que se ha compilado la clase "binvenida.class"). Veremos como en la Consola aparece "Hola Mundo".

Ahora vamos a instalar el pluggin "subclipse" en el eclipse, que sirve para poder acceder al repositorio. Descargar aquí. Descomprimimos el contenido en una carpeta cualquiera (en el escritorio por ejemplo). Nos vamos al eclipse y seguimos las instrucciones de la instalación de la web http://subclipse.tigris.org/install.html:
  • Help/Software Updates/Find and install
  • Activamos el radio button "Search for new features to install"/next
  • Clikeamos en el botón "New local site" y seleccionamos la carpeta que contiene el subclipse. Aceptamos y damos Finish.
  • Activamos el checkbox raiz que aparece, con lo que se activan los dos inferiores. Ahora desactivamos el checkbox del medio. Siguiente.
  • Activamos el radio button "I accept the terms in the license agreement". Siguiente -> Finish ->Install All
  • Le decimos que sí a reiniciar el Eclipse.
  • En Window/Open perspective/Other, seleccionamos el "SVN Repository Exploring" y OK. Veremos como cambia la vista de Eclipse. Para volver a la vista anterior, en Eclipse, en la esquina superior derecha de donde pone SVN RepositoryExploring Perspective, vemos un boton que pone ">>", se abre un menú y seleccionamos "JAVA".
  • Ahora vamos a abrir la ventana de los repositorios: Window/Show view/Other. Abrimos SVN Repository.
  • Abrimos el link: http://code.google.com/p/eticom-master-java/, pinchamos en la pestaña SOURCE y copiamos la URL que aparece hasta trunk, en nuestro caso http://eticom-master-java.googlecode.com/svn/trunk/.
  • En eclipse, en SVN Repository, menú contextual/new/repository location... y le pegamos la URL anterior, y finish. Ahora nos tiene que aparecer en la ventana de los repositorios la localización anteriormente insertada.
  • Ahora abrimos el link http://code.google.com/hosting/createProject, y creamos un nuevo repositorio en googlecode. Le damos un nombre (el mio es "pripro"), escribimos una descripción y seleccionamos una licencia (apache 2.0). Pulsamos el botón Create Project.
  • Nuevamente nos vamos al SOURCE de googlecode y de alguna manera, en googlecode, nos genera un password. Copiamos la 1ª dirección que nos sale, la https:// (https://pripro.googlecode.com/svn/trunk/).
  • En eclipse, en SVN Repository, menú contextual/new/repository location... y le pegamos la URL anterior, y finish. Ahora nos pide el nombre de usuario y el password anteriormente generado. OK y nos aparece el repositorio en la ventana de SVN Repository.
Ahora explicaremos como descargar desde el repositorio a nuestro workspace:
  • File/new/project. Abrimos la carpeta SVN y seleccionamos "Checkout Projects from SVN" y next.
  • Seleccionamos de la lista, la dirección https://pripro.googlecode.com/svn/trunk/. Seleccionamos nuestro proyecto (en este caso "bienvenida" y pulsamos Siguiente.
  • Seleccionamos el radio button "Check out as project in the workspace". Como Project Name: pripro, siguiente/finish.
Compartir el proyecto bienvenida (subirlo al repositorio):
  • En la ventana Navigator de Eclipse, menú contextual sobre el proyecto bienvenida/team/share project/SVN/Siguiente
  • En la ventana que se abre, seleccionamos el radio button "Use existing repository location" y de las dos URLs seleccionamos la https://pripro.googlecode.com/svn/trunk/ y pulsamos Finish. A continuación deseleccionamos los classpath y los project. OK.
Si lo que queremos es actualizar el proyecto bienvenida al repositorio, guardando los cambios realizados en el ordenador Local: sobre el proyecto, menú contextual/team/commit. También está Team/Update y Team/revert