Técnicas avanzadas de programación Introspección

Slides:



Advertisements
Presentaciones similares
CJ02 – Técnicas avanzadas en java 1.4 y 5.0
Advertisements

Curso de java básico (scjp)
DESARROLLO DE SOLUCIONES EMPRESARIALES MOVILES USANDO TECNOLOGIA SUN APLICACIONES MOVILES CON J2ME RMS Ing. Ronald Criollo.
Curso de Java Capitulo 7: Conceptos sobre poo Profesor:
Herencia en C#.
Lenguaje de programación Java
Clases Extendidas La clase extendida hereda los campos y métodos de la clase de la cual extiende. La clase original se conoce como superclase y la clase.
Arquitectura CLARO-TECNOTREE
Conceptos más avanzados de Programación Orientada a Objetos Programación 2005 Licenciatura de Lingüística y Nuevas Tecnologías.
Arquitectura CLARO-TECNOTREE CAPITULO 4: Excepciones
Capitulo 4 Excepciones.
Genéricos en Java Jaime Ramírez, Ángel Lucas González
Herencia y Polimorfismo
RMI (Remote Method Invocation)
Aplicación del paradigma orientado a objetos
Diseño y programación de
Encapsulamiento y Abstracción
PROGRAMACIÓN EN JAVA Curso-taller inicial de programación en JAVA Facultad de Estadística e Informática TEMA II.
Tema 7: Polimorfismo Antonio J. Sierra. Índice Introducción. Sobrecarga de métodos. Objetos como parámetros. Paso de argumentos. Devolución de objetos.
10. Hilos Definición y ejecución Thread y Runnable
Herencia y Polimorfismo en JAVA
Lic. Rosemary Torrico Bascopé
Clases y objetos La unidad fundamental de programación OO son las clases. Conjunto de métodos y semántica Qué se va a hacer POO Clase: que define la implementación.
SCJP SUN CERTIFIED PROGRAMMER FOR JAVA 6. SCJP 6.0 SEMANA CINCO CONSOLE.
Tema 6: Clases Antonio J. Sierra.
6. Herencia. Clases abstractas. Genericidad
Técnicas avanzadas de programación Interfaces
Introducción a Java (II)
SCJP Sun Certified Programmer for Java 6
UNIDAD 2 CLASES Y OBJETOS. CLASE Elementos cabecera y cuerpo de la clase. Cabecera: aporta información fundamental sobre la clase en sí y constituye de.
ESTRUCTURA DE DATOS EN JAVA
Tema 11: Excepciones Antonio J. Sierra.
Patrones Creacionales
Introducción a Java (2ª parte) - excepciones, colecciones, i/o, … -
Diplomado Desarrollo de Aplicaciones en Internet
PATRON PROTOTYPE Cristina Merino Héctor Carbajo Alicia Arroyo.
UNIDAD VI Recursos esenciales de Java LSC. Natalia Rodríguez Castellón.
SCJP SUN CERTIFIED PROGRAMMER FOR JAVA 6
Metodología de Programación Ayudantía 5 lelagos.ublog.cl 2009.
Informatica II1 Clases Extendidas La clase extendida hereda los campos y métodos de la clase que ha sido extendida. La clase original se conoce como superclase.
Programación avanzada en Java Miguel Ángel Corella 26 de Septiembre de 2005.
1 Interfaces y Clases Internas ELO-329: Diseño y programación orientados a objetos Agustín J. González.
Clases y Objetos en Java ELO329: Diseño y Programación Orientados a Objetos.
Herencia. Introducción La idea básica es poder crear clases basadas en clases ya existentes. Cuando heredamos de una clase existente, estamos re-usando.
Unidad 2.1: INTRODUCCIÓN A LA ORIENTACIÓN A OBJETOS.
Funciones y Clases Amigas (Friend)‏ Miembros Estáticos (Static)
Detalles Generales sobre Java
Algoritmos y Programación III
Tratamiento de excepciones
Interfaces y Clases Internas
:: Prof. Yeniffer Peña Programación I Programación Orientada a Objetos Presentación.
Ing. Esp. Ricardo Cujar.  Lenguaje de programación orientado a objetos.  Desarrollado por Sun MicroSystems.  Independiente del Sistema Operativo gracias.
Invocación Dinámica en CORBA
Programación orientada a objetos Capítulo 9 Algo mas sobre herencias.
Metodología de Programación Ayudantía 4 lelagos.ublog.cl 2009.
Algoritmos y Programación III 4. Colecciones, excepciones Carlos Fontela, 2006.
Clases “ Es una Abstracción de un elemento del mundo real ”
Tratamientos Secuenciales Generalizados II Fundamentos de Programación Departamento de Lenguajes y Sistemas Informáticos Unidad Didáctica 19 Versión
Programación orientada a objetos La programación orientada a objetos o POO (OOP según sus siglas en inglés) es un paradigma de programación que usa objetos.
Factorías e Iterables Introducción del concepto de patrón de diseño Construcción de tipos para recorridos con for extendido Fundamentos de Programación.
Estructuras de control selectivas Fundamentos de Programación Departamento de Lenguajes y Sistemas Informáticos Versión Práctica 3.
Fundamentos de Programación Departamento de Lenguajes y Sistemas Informáticos Práctica 4 Versión Diseño de tipos Igualdad, representación, código,
Métodos en Java. Estructura de un programa en Java ► La relación con la vida misma la podemos ver en el siguiente comentario: Imaginemos que dos clases.
Las interfaces Predicate y Function Versión Unidad Didáctica 17 Fundamentos de Programación Departamento de Lenguajes y Sistemas Informáticos.
Diseño de tipos Igualdad, representación, código, copia y relación de orden Fundamentos de Programación Departamento de Lenguajes y Sistemas Informáticos.
Programación en Java Introducción a Java. Reseña histórica Surge en 1991 por Sun Microsystems Desarrollado para electrodomésticos Se buscaba un código.
Concepto de Tipo y Subtipo Diseño e Implementación Fundamentos de Programación Departamento de Lenguajes y Sistemas Informáticos Unidad Didáctica 10 Versión.
Tema 1: Concurrencia con Java
Programación en Java Introducción a Java. Reseña histórica Surge en 1991 por Sun Microsystems Desarrollado para electrodomésticos Se buscaba un código.
Transcripción de la presentación:

Técnicas avanzadas de programación Introspección

Introducción Java tiene interesantes mecanismos para cargar clases de manera dinámica, conocer sus métodos y atributos, etc. Son formas de obtener información interna de las clases, incluso los objetos Java pueden informarnos de su propia estructura. Por ello se llaman utilidades de introspección. La clase más importante es java.lang.Class. Es una clase que nos permite describir cualquier clase Java. Dicho de otra forma, es un descriptor o referencia de una clase. Un paquete relevante es java.lang.reflect

Conocer el tipo En tiempo de ejecución puede saber el tipo (clase) que manejamos: Si tenemos un objeto, puedo conocer su clase: Coche miCoche = new Coche(); Class clase = miCoche.getClass(); System.out.println("Clase:" +clase.getName() ); Lo que hemos hecho es obtener un descriptor de clase (tipo Class) mediante miCoche.getClass(). Este descriptor nos devuelve su nombre mediante getName() Si tenemos una clase (no hay instancias): Coche.class.getName() getName() nos devuelve el nombre de la clase, incluyendo la jerarquía de paquetes. En nuestro ejemplo: newInstance.dominio.Coche

Carga dinámica Podemos cargar de manera dinámica un objeto, es decir, determinar en tiempo de ejecución (y no en tiempo de programación) la clase que vamos a instanciar Primero haremos una pequeña clase (Coche) de prueba: package newInstance.dominio; public class Coche extends Vehiculo { private int plazas = 5; public Coche() {} public Coche( int plazas ) { this.plazas = plazas; } public int getPlazas() { return plazas; } public void setPlazas( int p ) { plazas = p; } public String toString() { try { return super.toString() + " Plazas:" + String.valueOf(plazas); } catch (Exception e) { return "-1"; } } A continuación crearemos un objeto del tipo Class, que es un descriptor de la estructura de datos o clase. Lo conseguimos con forName(). El paso siguiente es crear una instancia de la clase con newInstance(). Class clase = Class.forName( “newInstance.dominio.Coche” ); Object objeto = clase.newInstance(); System.out.println(“Coche:" + objeto.toString() ); Necesitamos al menos un constructor sin parámetros (Coche()) para el uso de newInstance() o bien no especificar ninguno. Pero, si se especifica uno que tenga parámetros (Coche( int plazas )), entonces debe también implementar uno sin parámetros, ya que este es el que usa newInstance() Hemos determinado la clase desde una cadena en el código (newInstance.dominio.Coche). Esto no es muy dinámico. Pero las posibilidades de carga dinámica son evidentes: Un ejemplo puede ser que en función de una acción del usuario podemos instanciar una clase u otra. En un archivo properties podemos tener la asociación de acciones y clases. Otro ejemplo: puedo cargar todas las clases que haya en un determinado directorio, sin tener que determinar estáticamente (a priori en el código) las clase que cargo.

Carga dinámica. Ejemplo (I) Vamos a instanciar todas las clases de un directorio (paquete). strDirClases se obtiene previamente desde un archivo properties: …. //// Obtengo directorio de clases File fDirClases = new File( strDirClases ); if ( !fDirClases.isDirectory()) { System.out.println("El directorio de clases no existe" ); return; } //// Obtengo clases del directorio File[] listaFicheros = fDirClases.listFiles( new ClassFileFilter() ); // Ver siguiente transparencia if (listaFicheros.length == 0) { System.out.println("No hay clases en el directorio de clases" ); //// Instancio clases System.out.println("\nClases instanciadas:" ); String strClase = ""; Object objeto = null; for (int i = 0; i < listaFicheros.length; i++) { // Quito el sufijo .class strClase = listaFicheros[i].getName().substring(0, listaFicheros[i].getName().indexOf(".")); //// lec es un lector de parámetros de archivo properties (en este ejemplo el paquete es “newInstance.dominio.”) Class clase = Class.forName( lec.getParametro("paquete") + strClase ); objeto = clase.newInstance(); System.out.println("Clase:" + strClase + " Objeto:" + objeto.toString() ); Resultado: Clases instanciadas: Clase:Coche Objeto:Id:1 Plazas:5 Clase:Vehiculo Objeto:Id:2

Carga dinámica. Ejemplo (II) En este ejmplo se obtienen los archivos .class del directorio fDirClases (tipo File) por medio de la llamada: File[] listaFicheros = fDirClases.listFiles( new ClassFileFilter() ); listFiles usa un filtro de ficheros para obtener sólo los .class. El filtro es una clase que implementa el interfaz java.io.FileFilter, lo que le obliga a implementar el método accept(). Este método devuelve true si el archivo (parámetro) pasa el filtro: public class ClassFileFilter implements java.io.FileFilter { public boolean accept(java.io.File f) { if (!f.isDirectory()) { String name = f.getName().toLowerCase(); return name.endsWith("class"); } return false;

Manejo de la estructura de la clase (I) Podemos obtener la clase madre, los atributos, constructores y métodos de una clase. Para ello usaremos java.lang.reflect. Para hallar la clase madre: Class clase = Class.forName( "newInstance.dominio.Coche"); Class claseMadre = clase.getSuperclass(); System.out.println( "Clase " + clase.getName() + ", hereda de " +claseMadre.getName()); Para atributos, métodos y constructores es muy sencillo: los atributos se representan por la clase Field, los constructores por Constructor y Method para los métodos. Partimos del descriptor de clase: El descriptor de clase tiene los métodos getFields(), getConstructors() y getMethod(), que nos devuelven arrays de los objetos que buscamos. Pero sólo nos devuelve elementos públicos, hay una versión “Declared” de cada método get que nos devuelve cualquier elemento (privado, protegido o público), por ejemplo: getDeclaredFields(). Field atrib[] = clase.getDeclaredFields(); // getFields() nos da solo los public printLista( "Atributos:", atrib ); //// Constructores y métodos Constructor cons[] = clase.getConstructors(); // Sólo public printLista( "Constructores:", cons ); …. public static void printLista( String titulo, Object obj[]) { System.out.println( titulo ); for ( int i = 0; i < obj.length; i++) System.out.println( " " + obj[i].toString()); }

Manejo de la estructura de la clase (II) Además podemos invocar un método. Primero debemos encontrarlo, para lo cual usamos el método getMethod(), especificando el nombre del método y los tipos de sus parámetros. En este caso buscamos el método “setPlazas”, que tiene un parámetro int: Class tiposParam[] = { int.class }; Method metSetPlazas = clase.getMethod( "setPlazas", tiposParam ); A continuación lo invocamos. También necesitamos un array, pero esta vez para los valores de los parámetros: Coche miCoche = new Coche(); Object argumentos[] = {7}; metSetPlazas.invoke( miCoche, argumentos ); Invoke: si el método es static el primer argumento (miCoche en nuestro ejemplo) puede ser null. El segundo puede ser null si no tiene parámetros, en concreto (Object[]) null. Para comprobar el resultado puede usar miCoche.toString()

Midiendo el tiempo Hay una forma sencilla de medir el tiempo de invocación de un método, con System.currentTimeMillis(): //// Busca método toString (de otra forma, recorriendo array de Method) y lo invoca //// Ojo: búsqueda imperfecta, en caso de sobrecarga de métodos, toma el primero //// Además con System.currentTimeMillis() medimos tiempo de llamada for ( int i = 0; i < mets.length; i++) { if ( mets[i].getName().equals( "toString") ) { System.out.println( "Encontrado método " + mets[i].getName()); long inicio = System.currentTimeMillis(); String cadena = (String) mets[i].invoke( miCoche, (Object[]) null); long fin = System.currentTimeMillis(); System.out.println( "Invocado método: " + cadena); System.out.println( "Tiempo empleado por invoke(): " + (fin - inicio)); }