Custom Methods JavaBeans: Interaction with Components

Ivan Marsic • Rutgers University 256 A simple way to solve this problem is to check for all possible objects using instanceof, the operator that lets you test at run-time, whether or not an object is of a given type. A more advanced way is supported by the java.lang.reflect package, which lets you find out almost anything you want to know about an object’s class at run-time. An important class for reflection is the class Class, which at first may sound confusing. Each instance of the class Class encapsulates the information about a particular class or interface. There is one such object for each class or interface loaded into the JVM. There are two ways to get an instance of class Class from within a running program: 1. Ask for it by name using the static method forName: Class fooClass = Class.forNameFoo; This method will return the Class object that describes the class Foo 2. Ask an instance of any Object for its class: Foo f = new Foo; Class fooClass = f.getClass; As a side note, this construct is legal: Class classClass = Class.forNameClass; It returns back the instance of Class that describes the class Class. Once you have a Class object, you can call methods on it to find out information about the class. None of the methods are mutators, so you cannot change the class at run-time. However, you can use it to create new instance of a class, and to call methods on any instance. Some of the methods available in class Class are: Constructor getConstructorClass[] paramTypes; Constructor[] getConstructors; Field getFieldString name; Field[] getFields; Method getMethodString name, Class[] paramTypes; Method[] getMethods; boolean isInstanceObject obj; boolean isPrimitive; String getName; Chapter 7 • Software Components 257 String toString; The return types Constructor, Field, and Method are defined in the package java.lang.reflect .

7.3.2 Reification

For the meta-level to be able to reflect on several objects, especially if they are instances of different classes, it must be given information regarding the internal structure of objects. This meta-level object must be able to find out what are the methods implemented by an object, as well as the fields attributes defined by this object. Such base-level representation, that is available for the meta-level, is called structural meta-information. The representation, in form of objects, of abstract language concepts, such as classes and methods, is called reification. Base-level behavior, however, cannot be completely modeled by reifying only structural aspects of objects. Interactions between objects must also be materialized as objects, so that meta-level objects can inspect and possibly alter them. This is achieved by intercepting base-level operations such as method invocations, field value inquiries or assignments, creating operation objects that represent them, and transferring control to the meta level, as shown in Figure 7-3. In addition to receiving reified base-level operations from the reflective kernel, meta-level objects should also be able to create operation objects, and this should be reflected in the base level as the execution of such operations. A reflective kernel is responsible for implementing an interception mechanism. The method invocation is reified as an operation object and passed for the callee’s meta-object to reflect upon handle. Eventually, the meta-object requests the kernel to deliver the operation to the callee’s replication object, by returning control as in the diagram or performing some special meta-level action. Finally, the result of the operation is reified and presented to the meta-object. caller kernel op : Operation res : Result handleop : MetaObject methodarg obj : Object methodarg result createobj, method, arg op result createop, result res handleres Figure 7-3. Reifying an operation. See text for explanation.