Java Q&A
by Michael Travers

Example 1:
(a)
skij> (define button (new 'java.awt.Button "Press Me"))
  <<< #<java.awt.Button[button0,0,0,0x0,invalid,label=Press Me]>

(b)
skij> (invoke button 'setLabel "Please Press Me")
skij> (define window (new 'java.awt.Frame))
  <<< #<java.awt.Frame[frame1,0,0,0x0,invalid,hidden,layout=java.awt.BorderLayout,resizable,title=]>
skij> (invoke window 'setVisible #t)
skij> (invoke window 'add button)
;;; Hm, we still can't see anyting
skij> (invoke window 'getSize)
  <<< #<java.awt.Dimension[width=112,height=27]>
skij> (invoke window 'setSize 300 200)
;;; The window grows, but still we can't see the button!
skij> (invoke window 'show)

(c)
(invoke-static 'java.lang.Thread 'sleep (long 100))

(d)
skij> (peek (invoke button 'getSize) 'width)
  <<< 292

(e)
skij> (peek-static 'java.lang.System 'out)
  <<< #<java.io.PrintStream@3ae82e8c>

(f)
skij> (define listener (new 'com.ibm.jikes.skij.misc.GenericCallback
                            (lambda (event)
                               (print "That tickles!"))))
  <<< #<com.ibm.jikes.skij.misc.GenericCallback@8bbc2e8c>
skij> (invoke button 'addActionListener listener)

Listing One
import java.lang.reflect.*;
import java.util.Vector;
class SimpleDynvoke {
  // A simplified version of the real Invoke. Doesn't handle statics, 
  // constructors, primitives, java2, caching, null arguments
  public static Object invoke(Object obj, String methodName, 
                 Object[] args) throws NoSuchMethodException, Throwable {
    Class myClass = obj.getClass();
    Class[] signature = classArray(args);
    Method method = lookupMethod(myClass, methodName, signature);
    if (method == null)
      throw new NoSuchMethodException("no applicable method");
    else {
      try {
        // actually invoke the method
        return method.invoke(obj, args); }
      // pass exceptions upward.
      catch (InvocationTargetException e) {
        throw(e.getTargetException()); }
    }
  }
  static Method lookupMethod(Class target, String name, 
                      Class[] argClasses) throws NoSuchMethodException {
    // first try for exact match
    try {
      Method m = target.getMethod(name, argClasses);
      return m;
    }
    catch (NoSuchMethodException e) {
     if (argClasses.length == 0) { // if no args & no exact match, out of luck
        return null; }
    }
    // go the more complicated route
    Method[] methods = target.getMethods();
    Vector goodMethods = new Vector();
    for (int i = 0; i != methods.length; i++) {
      if (name.equals(methods[i].getName()) &&
          matchClasses(methods[i].getParameterTypes(), argClasses))
        goodMethods.addElement(methods[i]);
    }
    switch (goodMethods.size()) {
    case 0: {
      return null; }
    case 1: {
      return (Method)goodMethods.firstElement(); }
    default: {
      return mostSpecificMethod(goodMethods);
    } }
  }
  // 1st arg is from method, 2nd is actual parameters
  static boolean matchClasses(Class[] mclasses, Class[] pclasses) {
    if (mclasses.length == pclasses.length) {
      for (int i = 0; i != mclasses.length; i++) {
        if (!matchClass(mclasses[i], pclasses[i])) {
          return false; }
      }
      return true;
    }
    return false;
  }
  static boolean matchClass(Class mclass, Class pclass) {
    return mclass.isAssignableFrom(pclass);
  }
  static Method mostSpecificMethod(Vector methods) 
                                           throws NoSuchMethodException {
    for (int i = 0; i != methods.size(); i++) {
      for (int j = 0; j != methods.size(); j++) {
        if ((i != j) &&
            (moreSpecific((Method)methods.elementAt(i), (Method)methods.elementAt(j)))) {
          methods.removeElementAt(j);
          if (i > j) i--;
          j--;
        }
      }
    }
    if (methods.size() == 1)
      return (Method)methods.elementAt(0);
    else
      throw new NoSuchMethodException(">1 most specific method");
  }
  // true if c1 is more specific than c2
  static boolean moreSpecific(Method c1, Method c2) {
    Class[] p1 = c1.getParameterTypes();
    Class[] p2 = c2.getParameterTypes();
    int n = p1.length;
    for (int i = 0; i != n; i++) {
      if (!matchClass(p2[i], p1[i])) {
        return false;
      }
    }
    return true;
  }
  // given an array of objects, return an array of corresponding classes
  static Class[] classArray(Object[] args) {
    Class[] classes = new Class[args.length];
    for (int i = 0; i != args.length; i = i + 1)
      classes[i] =  args[i].getClass();
    return classes;
  }
}








3


