220 likes | 301 Views
Reflection In Java. “Reflection is the ability of a program to manipulate as data something representing the state of the program during its own execution.” [Demers and Malenfant] For every loaded class, the JVM maintains an associated Class object
E N D
Reflection In Java “Reflection is the ability of a program to manipulate as data something representing the state of the program during its own execution.” [Demers and Malenfant] • For every loaded class, the JVM maintains an associated Class object • The Class object “reflects” the class it represents • The primitive Java types are also represented as Class objects • Instances of the class Class store information about classes • Class name • Inheritance • Interfaces implemented • Methods, members, etc. • Can look up instances: By name or From an object
Accessing the Class object To get the Class object for an object mystery: Class c = mystery.getClass(); Or, using the class type: Class c = mysteryClass.class; Or, using the class name: Class c = Class.forName(“mysteryClass”); Getting the superclass of MysteryClass: Class s = c.getSuperclass(); Getting the class name: String s = c.getName(); Discovering the interfaces implemented by a class: Class[] interfaces = c.getInterfaces(); Discovering the fields of a class: Field[] fields = c.getFields(); Discovering the methods of a class: Method[] methods = c.getMethods();
Example – exploring a type publicstaticvoid showType(String className) throws ClassNotFoundException { Class thisClass = Class.forName(className); String flavor = thisClass.isInterface() ? "interface" : "class"; System.out.println(flavor + " " + className); Class parent = thisClass.getSuperclass(); if (parent != null) { System.out.println("extends " + parent.getName()); } Class[] interfaces = thisClass.getInterfaces(); for (int i=0; i<interfaces.length; ++i) { System.out.println("implements "+ interfaces[i].getName()); } }
The Output class java.lang.Object class java.util.HashMap extends java.util.AbstractMap implements java.util.Map implements java.lang.Cloneable implements java.io.Serializable class Point extends java.lang.Object
Displaying Methods staticvoid showMethods(Object o) { Class c = o.getClass(); Method[] theMethods = c.getMethods(); for (int i = 0; i < theMethods.length; i++) { String methodString = theMethods[i].getName(); System.out.println("Name: " + methodString); System.out.println(" Return Type: " + theMethods[i].getReturnType().getName()); Class[] parameterTypes = theMethods[i].getParameterTypes(); System.out.print(" Parameter Types:"); for (int k = 0; k < parameterTypes.length; k ++) { System.out.print(" " + parameterTypes[k].getName()); } System.out.println(); } }
Output Output for a call of the form: Polygon p = new Polygon(); showMethods(p); . . Name: equals Return Type: boolean Parameter Types: java.lang.Object Name: getClass Return Type: java.lang.Class Parameter Types: Name: intersects Return Type: boolean Parameter Types: double doubledoubledouble
Main Java reflection Classes • Class ( java.lang.Class ) • Instances of the class Class represent classes and interfaces in a running Java application, every object is represented by a Class object. • Package java.lang.reflect: • Member ( java.lang.reflect.Member ) • An Interface that reflects identifying information about a single member (a field or a method) or a constructor. • Method ( java.lang.reflect.Method ) • Implements Member Interface • provides information about, and access to, a single method on a class or interface. • Represents instance methods and class methods ( static ) • Field • Implements Member Interface • provides information about, and dynamic access to, a single field ( also for static fields ) • Provides access and modification ( set, get ) methods.
Main Java reflection Classes • Constructor • provides information about, and access to, a single constructor for a class. • Package • Package objects contain version information about the implementation and specification of a Java package • Modifier • provides static methods and constants to decode class and member access modifiers. The sets of modifiers are represented as integers with distinct bit positions representing different modifiers
Reflection API Interface - example class Class{static Class forName(String name); Object newInstance(); Field getField(String name); Method getMethod(String name, Class[] paramTypes); //other methods: getName(), getInterfaces(), // getSuperclass(), getModifiers(), // getFields(), getMethods(), … } class Field extends AccessibleObject { Object get(Object obj);void set(Object obj, Object val); //other methods: getType(), getDeclaringClass(), ... }
Exploring the Instantiation Hierarchy publicstaticvoidmain(String[] args){ traverse(new Integer(3)); } L1: 3.getClass() = class java.lang.Integer L2: class java.lang.Integer.getClass() = class java.lang.Class L3: class java.lang.Class.getClass() = class java.lang.Class publicstaticvoid traverse(Object o){ for (int n = 0; ; o = o.getClass()) { System.out.println("L"+ ++n + ": " + o + ".getClass() = " + o.getClass()); if (o == o.getClass()) break; } }
Using Arrays publicstaticvoidtestArray(){ Class cls = String.class; inti=10; Object arr = Array.newInstance(cls, i); Array.set(arr, 5, "this is a test"); String s = (String)Array.get(arr, 5); System.out.println(s); } Reflection can be used to create and manipulate arrays whose size and component type are not known until runtime
A Java Reflection Example • Illustrates Four Issues: • Runtime type Information (RTTI) • Introspection • Invoking Method Objects • Dynamic Instantiation
Back to our Employee Example… Employee number level print() Only partial view of the classes… HourlyEmployee print() MonthlyEmployee print() public final class MonthlyEmployee extends Employee { publicvoid print() { System.out.println("I’m a Monthly Employee"); } } public final class HourlyEmployee extends Employee { publicvoid print() { System.out.println("I’m a Hourly Employee"); } }
Reflection and Dynamic Binding What is the output of the following test code: Employee e; e = new MonthlyEmployee(); Class c = e.getClass(); System.out.println("class of e = " + c.getName()); e = new HourlyEmployee(); c = e.getClass(); System.out.println("class of e = " + c.getName()); class of e = MonthlyEmployee class of e = HourlyEmployee
SuperClass What is the output of the following test code: c = c.getSuperclass(); System.out.println("base class of e = " + c.getName()); c = c.getSuperclass(); System.out.println("base of base class of e = " + c.getName()); base class of e = Employee base of base class of e = java.lang.Object
Getting and setting fields • Non public fields are not printed! • getDeclaredFields returns all fields declared by the class, but excludes inherited ones Field fields[] = c.getFields(); for(inti = 0; i < fields.length; i++) { System.out.print(fields[i].getName() + "= "); System.out.println(fields[i].getInt(e)); } The output produced: number= 111 level= 12 e is an instance of Employee or its subtype Field f = c.getField("level"); f.setInt(e,f.getInt(e)+1);
Examining Modifiers What is the output of the following test code: int m = c.getModifiers(); if (Modifier.isPublic(m)) System.out.println("public"); if (Modifier.isAbstract(m)) System.out.println("abstract"); if (Modifier.isFinal(m)) System.out.println("final"); public final
Invoking Method Objects • We can ask a method object to invoke the method it represents • we must provide it with the implicit and explicit arguments Employee e = new HourlyEmployee(); Class c = e.getClass(); Method m = c.getMethod("print", null); m.invoke(e, null); the output produced: I’m a Hourly Employee
Dynamic Instantiation The universal printer gets the employee type and invokes the print method. class UniversalPrinter { publicvoid print(String empType) { Class c = Class.forName(empType); Employee emp = (Employee ) c.newInstance(); emp.print(); } } -for calling other constructors (with arguments), use the Constructor class - Constructor c = ... - Object newObject = c.newInstance( Object[] initArguments ) What is the output of the following code? UniversalPrinter p = newUniversalPrinter(); String empType; empType = "HourlyEmployee"; p.print(empType); empType = "MonthlyEmployee"; p.print(empType);
Implementing Java Reflection class Class { String name; Field[] fields; Method[] methods;boolean primitive; boolisInstance... Object newInstance.. } class Field { String name; Class type; Class clazz;int offset; Object get(Object obj) { if (clazz.isInstance(obj)) { f = ((char*)obj) + offset; return (type.primitive = TRUE ? wrap(f) : (Object)f); } }} • At runtime, JVM loads class files and creates objects representing the classes. • Object representing a class has a name (string field), list of fields (each of type Field) , list of methods…
Reflection - What’s missing • Reflection is introspection only • Cant add / modify fields (structure), methods (behavior) • Implementation is not available • Program logic is not reflected • Major performance impact • Much slower then doing the same operations directly… • Complex code
Java Serialization publicclassPersistentTimeimplementsSerializable{private Date time; publicPersistentTime(){ time = Calendar.getInstance() .getTime(); } public Date getTime(){return time;}} String filename = "time.ser"; PersistentTime time = newPersistentTime();FileOutputStreamfos = null;ObjectOutputStream out = null;fos = newFileOutputStream(filename);out = newObjectOutputStream(fos);out.writeObject(time);out.close(); • the process of converting objects into a linear stream of bytes • Depends on reflection