Session 18: Reflection

Chapter 20 of the textbook talks about how in Smalltalk you can access features of your program, like classes and methods. Java has a facility like this too, called reflection. It's conceptually simpler and less powerful than Java's, but it's still useful and interesting.

This program implements a CheckedArray class, which allows the user to create an "array" of objects of a particular type. The program verifies that each item added to the "array" is of that type during run-time. It also provides a method, doAll, which applies a method to each item in the "array".

(This example is only somewhat realistic. Usually it's best to avoid reflection when possible, since it's not too easy or efficient. Note that, did Java have templates, this would make even less sense as an example. I have definitely found reflection useful in real contexts, but they have been significantly larger.)

 1  import java.lang.reflect.*;
   
 2  class CheckedArray {
 3      private Object[] data;
 4      private Class data_type;
   
 5      public CheckedArray(int len, Class data_type) {
 6          data = new Object[len];
 7          this.data_type = data_type;
 8      }
   
 9      public void set(int pos, Object info) {
10          if(!data_type.isInstance(info)) throw new RuntimeException("bad");
11          data[pos] = info;
12      }
   
13      public Object get(int pos) {
14          return data[pos];
15      }
   
16      public void doAll(String meth_name, Object[] args) {
17          Class[] parms = new Class[args.length];
18          for(int i = 0; i < args.length; i++) {
19              parms[i] = args[i].getClass();
20          }
21          try {
22              Method meth = data_type.getMethod(meth_name, parms);
23              for(int i = 0; i < data.length; i++) {
24                  meth.invoke(data[i], args);
25              }
26          } catch(NoSuchMethodException e) {
27              throw new RuntimeException(e);
28          } catch(InvocationTargetException e) {
29              throw new RuntimeException(e);
30          } catch(IllegalAccessException e) {
31              throw new RuntimeException(e);
32          }
33      }
34  }

The following illustrates how this class might be used in a program.

35  class Person {
36      private String name;
   
37      public Person(String name) { this.name = name; }
38      public String getName() { return name; }
39      public void printName() { System.out.println(name); }
40      public void talk(Person other) {
41          System.out.println("hi " + other.getName());
42      }
43  }
   
44  class Student extends Person {
45      public Student(String name) { super(name); }
46      public void talk(Person other) {
47          System.out.println("hello " + other.getName());
48      }
49  }
   
50  class Test {
51      public static void main(String[] args) {
52          CheckedArray arr = new CheckedArray(2, Person.class);
53          arr.set(0, new Person("Carl"));
54          arr.set(1, new Student("Andrew"));
55          arr.doAll("printName", new Object[] {});
56          arr.doAll("talk", new Object[] { arr.get(0) });
57      }
58  }