Introdução à reflexão em Java 1 Cátia Vaz 2010/2011 O que é a reflexão? } Reflexão, o que é? } } } – Disponibilização, via API, de informação de tipo (metadata) em tempo de execução. – Em Java esta API é composta pelas classes do package java.lang.reflect Introspeção, o que é? } – Realização de código genérico que tira partido da existência de reflexão } 2 Cátia Vaz 2010/2011 java.lang.Class } Para cada tipo de objecto, a JVM cria uma instância imutável de java.lang.Class } } 3 java.lang.Class disponibiliza métodos para examinar as propriedades de runtime de um objeto incluindo os seus membros e informação de tipo. Class permite criar novas classes e objetos. Cátia Vaz 2010/2011 Aceder à metadata } Java armazena metadata em classes: } } } } } Metadata para uma: java.lang.Class Metadata para um construtor: java.reflect.Constructor Metadata para um campo : java.reflect.Field Metadata para um método: java.reflect.Method Para aceder a um objecto Class para uma classe: } } 4 Class<?> c1=Class.forName(“java.util.Properties”); Object obj = ...; Class<?> c2 = obj.getClass(); Cátia Vaz 2010/2011 Exemplos class Class { Constructor[] getConstructors(); Field getDeclaredField(String name); Field[] getDeclaredFields(); Method[] getDeclaredMethods(); public String getName(); public boolean isArray(); public boolean isInterface(); public boolean isPrimitive(); public Class getComponentType(); ... } class Field { Class getType(); ... } class Method { Class[] getParameterTypes(); Class getReturnType(); ... } 5 Cátia Vaz 2010/2011 Metadata para tipos primitivos e arrays } Java associa uma instância de Class com cada tipo primitivo: } } } } Class<?> c1 = int.class; Class<?> c2 = boolean.class; Class<?> c3 = void.class; Usar Class.forName() para aceder a um objecto Class para um array } } Class<?> c4 = byte.class; Class<?> c5 = Class.forName(“[B”); // byte[] Class<?> c6 = Class.forName(“[[B”); // byte[][] Class<?> c7 = Class.forName(“[Ljava.util.Properties”); } 6 B -> byte; C -> char; D ->double; F -> float; I -> int; J -> long; Lclassname -> class-name[]; S -> short; Z -> boolean Cátia Vaz 2010/2011 Invocar um construtor } Invocar o construtor por omissão Class<?> c = Class.forName(className); c.newInstance(); } Invocar outros construtores Constructor<?> cons = c.getConstructor( new Class[] {String.class, String.class}) cons.newInstance( new Object[]{“x”, “y”}); 7 Cátia Vaz 2010/2011 Procurar por métodos } Pode procurar-se : } } Os métodos públicos, numa classe ou numa classe hierarquicamente ascendente Ou procurar um método público ou não declarado na própria classe class Class { public Method getMethod(String name, Class[] parameterTypes); public Method[] getMethods(); public Method getDeclaredMethod(String name, Class[] parameterTypes); public Method[] getDeclaredMethods(); ... } 8 Cátia Vaz 2010/2011 Invocar um método Object obj = ... Class<?> c = obj.getClass(); Method m = c.getMethod(“doWork”, new Class[] {String.class, String.class}); Object result= m.invoke(obj, new Object[]{“x”,“y”}); 9 Cátia Vaz 2010/2011 Procurar um campo } Pode procurar-se: } } Um campo público numa classe ou nas suas classes hierarquicamente ascendentes Um campo, publico ou não, declarada numa classe específica class Class { public Field getField(String name); public Field[] getFields(); public Field getDeclaredField(String name); public Field[] getDeclaredFields(); … } 10 Cátia Vaz 2010/2011 Aceder a um campo Object obj = ... Class<?> c = obj.getClass(); Field f = c.getField(“firstName”); f.set(obj, “John”); Object value = f.get(obj); 11 Cátia Vaz 2010/2011 Descobrir um campo herdado Field findField(Class cls, String fieldName) { Field field = null; while (cls != null) { try { field = cls.getDeclaredField(fieldName); break; } catch (NoSuchFieldException ex) { cls = cls.getSuperclass(); } } return field; } 12 Cátia Vaz 2010/2011 Java modifiers } Java define 11 modificadores: } } Alguns modificadores podem ser aplicados a uma classe, método ou campo: } } abstract, final, native, private, protected, public, static, strictfp, synchronized, transient and volatile Obtem-se o conjunto dos modificadores invocando o método int getModifiers() Alguns métodos estáticos úteis em java.lang.reflect.Modifier: static boolean isAbstract(int modifier); static boolean isFinal(int modifier); static boolean isNative(int modifier); static boolean isPrivate(int modifier); 13 Cátia Vaz 2010/2011 Aceder a campos e objectos não público } As classes Field e Method definem os seguintes métodos (herdados de java.lang.reflect.AccessibleObject): boolean isAccessible(); void setAccessible(boolean flag); static void setAccessible(AccessibleObject[] array, boolean flag); Exemplo if(!Modifier.isPublic(field.getModifiers()) { field.setAccessible(true); } Object obj = field.get(obj); 14 Cátia Vaz 2010/2011