Jugando con Reflection

Uno de los mejores inventos del siglo pasado es sin dudas la API Reflection de Java, extrañamente me veo rodeado a menudo de gente que, o bien no la conoce, o bien le da miedo. A los primeros solo puedo darles el consejo de que lean el capitulo 9 del libro Hardcore Java para que se enteren de que va, a los segundos solo puedo darles la razón…La API Reflection es como un martillo, lo podemos usar para construir una iglesia o para romperle la cabeza a alguien, despues no sirve para nada. Así, usar esta API permite que nuestros programas interactuen con clases de las cuales no conoce absolutamente nada (nos podemos olvidar de implementar interfaces!) ó bien podemos hacer un “bypass” de los modificadores de acceso haciendo inservible a cualquier objeto. Dominar la API Reflection para no caer en las incontables tentaciones que nos ofrece es una disciplina de autocontrol digna de un arte marcial.

Para los que no se avisparon todavia de que va la API Reflection la idea es basicamente manipular “metainformación” de las clases en tiempo de ejecucion para poder conocer los metodos, propiedades ó constructores de clases que quiza ni sabiamos que existian. A continuacion dejo un pedazo de codigo que muestra las virtudes, a veces peligrosas, de esta API.

public class Perro {
private void ladrar() {
System.out.println(“GUAU!”);
//un metodo privado para ladrar.
}
}

public class PruebaReflection {
public static void main(String[] args) {
Perro p = new Perro(); //Nada del otro Mundo.
Class clase = p.getClass();
//A no confundir Class con class. El
// metodo
getClass() devuelve un objeto
//de clase Class
con la “metadata” de la
// clase Perro :S

Method metodo = clase.getDeclaredMethod(“ladrar”) //Method es a los
//metodos lo que Class
// es a las clases

metodo.setAccesible(true) //wow.. le decimos que ignore los
// modificadores
de acceso del metodo.
metodo.invoke(p);
//el metodo invoke de la clase Method permite
// invocar a
un metodo sobre un objeto en
//particular, en este caso
sobre nuestro Perro p.
}
}

Si ejecutamos el codigo aparecera en la pantalla GUAU! que a priori no podriamos haber accedido por ser privado de la clase Perro ¿Aterrador verdad?. En el otro extremo imaginense la tarea de armar la GUI de un CRUD (create, read, update, delete…) para nuestro modelo. No es negocio hacer a mano una ventana para cada clase que participa en nuestro modelo, en cambio podemos aprovechar la API Reflection para que en tiempo de ejecucion arme dinamicamente las ventanas de acuerdo a las propiedades que encuentre en las clases que les indicamos. ¿Nos ahorraria bastante tiempo, no?

Caminar una colección

Mucho ojo al tratar de caminar una colección:

ConcurrentModificationException This exception may be thrown by methods that have detected concurrent
modification of an object when such modification is not permissible.

Note that this exception does not always indicate that an object has
been concurrently modified by a /different/ thread. If a single thread
issues a sequence of method invocations that violates the contract of an
object, the object may throw this exception. For example, if a thread
modifies a collection directly while it is iterating over the collection
with a fail-fast iterator, the iterator will thow this exception.

http://java.sun.com/j2se/1.4.2/docs/api/java/util/ConcurrentModificationException.html

Esto es culpa del Iterator a traves del cual recorremos la clase (por mas que usemos un “enhanced for” en el fondo sigue habiendo un iterator) y hay que recordar que no se puede modificar una lista, agregando o eliminando objetos, mientras la estamos recorriendo con un iterator.

Herencia multiple en Java

Recuerden que las Interfaces SI soportan herencia multiple.


public interface Parent1 {
public String metodo1();
}

public interface Parent2 {
public String metodo2();
}

public interface Child extends Parent1, Parent2 {
}

Esto funciona correctamente aunque hay que tener ciertas precauciones. La interfaz Child puede extender dos (o mas) interfaces siempre y cuando no haya conflictos entre los metodos declarados en ellas. Si Parent1 hubiera tenido un metodo public void metodo() y Parent2 un metodo public int metodo() un error de compilacion nos indicaria que Parent1 y Parent2 son interfaces incompatibles pues no se puede sobrecargar un metodo unicamente por el tipo de retorno.
Algo parecido sucede con las constantes. Si las interfaces Parent1 y Parent2 poseen una constante VALOR del mismo tipo aparecen conflictos para acceder a estos valores desde la clase que implemente Child, por ejemplo ImpChild, si tratamos de acceder a la constante usando Child.VALOR o ImpChild.VALOR. En este caso deberiamos indicarle exactamente que constante queremos, si VALOR de Parent1 o VALOR de Parent2.

Como dicen por ahí: Curioso pero inútil :)

Matematicas de Java

Here is an example of a widening conversion that loses precision:

class Test {
public static void main(String[] args) {
int big = 1234567890;
float approx = big;
System.out.println(big – (int)approx);
}
}

which prints:

-46

thus indicating that information was lost during the conversion from type int to type float because values of type float are not precise to nine significant digits.

Entradas y comentarios feeds. 14 queries. 0.299 seconds.

60920 pages viewed, 15 today
29269 visits, 10 today
FireStats icon Powered by FireStats