View
223
Download
2
Tags:
Embed Size (px)
Citation preview
Advanced Java Course
Reflection
Reflection API
• What if you want to access information not just about the Object, but about that Object’s Class?
• What if you want to access a method, field, or constructor whose name you don’t know at compile time?
Example: WebCrawler timer
• To optimize your WebCrawler, first find out how long each big operation is taking.– Getting content from URLs– Parsing pages– Setting up Database Connection & Statement– Deleting from the Database– Inserting into the Database– Other?
How to time an operation?
• Without reflection:int startTime = System.currentTimeMillis();doOperation(...);int endTime = System.currentTimeMillis();int duration = endTime – startTime;
• Problem:Code is repeated every place you want to time an
operation! Not clean at all...
A better way to time an operation
• Object timeMethod(String methodToCall, Class[] argTypes, Object[] args, String timeToUpdateField) {...}
• timeMethod(“methodName”, new Class[] {...}, new Object[] {...}, “timeStoringField”);
• No code repetition, less clutter!
Classes in the Reflection API
• Class Class
• Class Constructor
• Class Field
• Class Method
Getting an Object of type Class
• If you have an instance of the class:– Class classObject = instanceObject.getClass();
• If you know the name of the class at compile time:– Class classObject = ClassName.class
• If you know the name of the class at run time:– Class.forName(“...”);
• If you want a primitive type class, and you know the name of the wrapper class at compile time;– Integer.TYPE, Long.TYPE, etc
some methods in the Class class
• getName()• getSuperClass()• getComponentType() – [null if !isArray()]
• isArray()• isInterface()• isPrimitive()
• isInstance(Object o)• Object newInstance()
Getting Constructors/Methods/Fields
• ask the Class Object for them– classObject.getConstructors()– classObject.getConstructor( Class[] argTypes)– classObject.getDeclaredConstructors()– classObject.getDeclaredConstructors( Class[] argTypes)
• Methods and Fields have analogous getters in class Class.
• you can get an array of all the c/m/f in the class, or just one by name, and if you ask for “Declared” it gives you the non-public ones as well.
Objects of Type Method
• calling a method dynamically:– Object methodObject.invoke(Object o,
Object[] args);
• getting info about it:– Class[] getParameterTypes()– Class getReturnType()– Class[] getExceptionTypes()
Objects of type Field
• Object fieldObject.get( Object o ); – also getInt(Object), getBoolean(Object), etc.
• void fieldObject.set( Object o, Object value );– also setInt(Object o, int i), etc.
• Class fieldObject.getType() [compile time, of course]
• Fields of type int will have Integer.TYPE as the result of getType(), and it’s a Class Object.
Objects of type Constructor
• Object constructorObject.newInstance( Object[] args )
• Class[] constructorObject.getExceptionTypes()
• Class[] constructorObject.getParameterTypes()
Member Interface
• Method, Field, and Constructor classes all extend the Member Interface
• Class getDeclaringClass()
• String getName()
• int getModifiers()
Modifier class (static methods)
• How do you know if something is static, final, etc.?
• int getModifiers() [from Member Interface]
• Modifer.isStatic(int)• Modifer.isFinal(int)• Modifier.isProtected(int)• etc.
Array class (static methods)
• Object Array.get(Object arrayObject, int i);
• void Array.set(Object arrayObject, int index, Object value)
• int Array.getLength(Object arrayObject);
• Object newInstance(Class type, int length)
• Object newInstance(Class type, int[] dimensions)
Reflection Group Task #1
• Fill in example from beginning of lecture:
Object timeMethod(String methodToCall, Class[] argTypes, Object[] args, String timeToUpdateField) {
...
Please fill this in!
...
}
Solution to Reflection Group Task 1 Object timeMethod(String methodToCall, Class[]
argTypes, Object[] args, String timeToUpdateField) throws NoSuchMethodException,
NoSuchFieldException, InvocationTargetException, IllegalAccessException
{ Class c = this.getClass(); long startTime = System.currentTimeMillis(); Method m = c.getMethod(methodToCall, argTypes); Object returnValue = m.invoke(this, args); long endTime = System.currentTimeMillis(); Field f = c.getField(timeToUpdateField); f.setLong(this, f.getLong(this) + (endTime - startTime)); return returnValue; }
Reflection Group Task #2Fill in the class definition to call all getX methods and print their values in the form:ClassName propertyName = value
import java.lang.reflect.*;public class PropertyValueFinder { final String GET = "get"; public void printProperties(Object o) { /*fill this in*/ } private Property propertyGottenBy(Method method) { /*fill this in*/} private boolean isGetter(Method method) { /*fill this in*/ } public class Property { String name; Class type; Object value; public Property(String name, Class type) { this.name = name; this.type = type; } public void setValue(Object value) { this.value = value; } public String toString() { return type+" "+name+" = "+value; } }}
Group Task #2 Solutions
private boolean isGetter(Method m) { boolean nameOK = m.getName().startsWith(GET); boolean noArgs = m.getParameterTypes().length == 0; boolean nonVOID = m.getReturnType() != Void.TYPE; return nameOK && noArgs && nonVOID; }
private Property propertyGottenBy(Method m) { if (!isGetter(m)) return null; Class propertyType = m.getReturnType(); String propertyName =
m.getName().substring(GET.length()); return new Property(propertyName, propertyType); }
Group Task #2 Solutionspublic void printProperties(Object o) { Class oClass = o.getClass(); Method[] methods = oClass.getMethods(); for (int i = 0; i < methods.length; i++) { Method m = methods[i]; if (isGetter(m)) { try { Object value = m.invoke(o, new Object[0]); Property p = propertyGottenBy(m); p.setValue(value); System.out.println(p); } catch (IllegalAccessException e) { throw new RuntimeException(); //programmer error } catch (IllegalArgumentException e) { throw new RuntimeException(); //programmer error } catch (InvocationTargetException e) { throw new RuntimeException(); //programmer error } } } }
Discussion Topic
• Restriction to Serializer project:• I must promise that the Objects I test your code on will
have a no-args constructor that:– sets the value of any final variables that are not set in the class
definition– does not throw any exceptions.
• If you could add functionality to the Reflection API, how would you fix this without compromising the integrity of the keyword final?
• Work in teams, and then we’ll exchange ideas.• Great, now go start a JSR (Java Specification Request)!
– http://www.jcp.org/en/participation/membership