Welcome!

Java Authors: Patrick Curran, Maureen O'Gara, Carmen Gonzalez, Michael Sheehan, Jonny Defh

Related Topics: Java

Java: Article

Restoring the "Delegate" Concept To Java

Had the "Delegate" Become Part of Java, Would Swing Programming Be Easier?

The function pointer, a powerful concept in the C and C++ programming languages, has no direct equivalent in Java. No syntax exists to pass the address of a method to a JButton, for instance, that links it with pressing the button. Instead, Java promotes the use of anonymous inner classes, like this one:


okButton.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent e) {
    startProcessing();
  }
});

Back in October 1996, in an attempt to eliminate the need for this bloated syntax, Microsoft introduced an object-oriented method pointer into J++ called a "delegate." Sun Microsystems, citing the delegate as language pollution, sued Microsoft a year later for violating its Java license agreement. The lawsuit successfully maintained the purity of Java, but it also encouraged Microsoft to develop a competing Java-like language, C#. Today, the delegate lives on in C# and the other .NET programming languages that comprise Microsoft's Common Language Runtime.

Had the delegate become part of Java, would Swing programming be easier? More than simply hooking a component to an action, the delegate could invoke methods directly or asynchronously on a worker thread. Could that technique have solved many of the Swing threading headaches that we're faced with today? This article explores these possibilities by using Java's reflection API to restore the delegate concept to Java.

Building a Delegate
java.lang.reflect.Method provides a description of a method including formal parameter types, return type, access modifier, declared exceptions, and annotations. It also provides an invoke() method to perform an indirect call; however, unlike a function pointer, Method is not bound to a particular object instance. It's part of a toolkit that includes Constructor and Field for inspecting classes. To use invoke() you must pass in a reference to an object instance.

Listing 1 demonstrates how to use it to call System.out.println() indirectly. Since the static member variable out is an instance of PrintStream, Line 4 calls getMethod() on the PrintStream Class passing in a description of the method that we're interested in. Note, many of the reflection API methods were retrofitted with varargs as of Java 5; previously, getMethod() accepted the method name followed by the method parameter types as a Class[]. Line 8 passes the string to print along with out to invoke() on the Method acquired in line 4.

To build a Delegate class, I joined together a Method and an object instance. Compare Listing 1 to the following snippet:


Delegate delegate = new Delegate(
  System.out, "println");
delegate.invoke("Hello World!");

First, notice the lack of exception handling. Internally, Delegate transforms checked exceptions into unchecked exceptions for cleaner code. Second, observe that when Delegate is constructed, the println() method is not fully described; the parameter types are absent. Delegate.invoke() completes the method resolution on the first call using getClass() on each argument. Subsequent calls reuse a cached Method; however, this technique, although convenient, fails when a null parameter is used on the initial call. An alternative constructor lets you specify the argument class types explicitly like this:


Delegate delegate = new Delegate(
  System.out, "println", String.class);
delegate.invoke("Hello World!");

Delegate seeks out and binds to methods of any access level, including private ones. Instead of using Class.getMethod(), which obtains only public methods, Delegate calls Class.getDeclaredMethod(). Unfortunately, both of those functions exclude inherited methods. To get around that, Delegate iteratively applies getDeclaredMethod() to all the classes in the hierarchy with the aid of Class.getSuperclass(). After locating the method of interest, Method.setAccessible(true) is used to suppress invocation access checking.

If you're surprised that you can call a private method from outside of an object, recognize that access modifiers were designed for code organization, not for security; they enable you to expose usage method while hiding implementation details. Suppressing access checking is highly beneficial for unit testing. Normally to unit test implementation methods, you have to grant them at least default (package) access; however, Delegate provides an alternative that lets you keep those methods private.

Since static methods are bound to classes, not instances, Delegate provides another constructor, which accepts a Class. The following example creates a Delegate to the Math.cbrt() function, a static method introduced in Java 5 to compute cube roots.


Delegate delegate = new Delegate(Math.class, "cbrt");
double x = (Double)delegate.invoke(8.0);

Delegate.invoke() returns type Object; in this case, the result is first cast to Double and then auto-unboxed to a double primitive.

More Stories By Michael Birken

Michael Birken is actively involved in the design and research of emerging trading technologies at a Manhattan-based financial software company. He's a Sun Certified Java programmer and developer. Michael holds a BS in computer engineering from Columbia University.

Comments (9) View Comments

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


Most Recent Comments
Black007_pl 05/20/08 10:28:41 AM EDT

Hi!
I don't really see the point of using delegates in java. The code with ActionListeners is more clear to me than using some function pointer, and passing them into UI elements. It implements observer/obesrvable pattern, and it's more objective for me than delegates... You can easily implement your won calls that will implement this pattern just by having a list of objects that implemet some interface and invoking it's method, nothing more....
And when I saw how my collegue tries to implemet his won delegates in C# it was very difficult to me to understand what his trying to do (he also didn't know it... :D )

Have a nice day

Tom 04/13/05 09:10:30 AM EDT

Oh, another suggestion is to use a more Microsoft alike approach. For example when instead of:

container.add(button)

the following is writen:

container.add(SwingEventDispatcher.wrap(button, "store", this));

This line still adds the button to the container, but also names the button "store" and binds it to "this" by searching for methods with a particular pattern, for example:

public void store_actionPerformed(ActionEvent e)

Note the "store_" prefix. To make the source more readable this method may also be written as:

public void store_clicked(ActionEvent e)

And some intelligence is added also:

public void store_singleClick(ActionEvent e)
public void store_doubleClick(ActionEvent e)
public void store_tripleClick(ActionEvent e)
public void store_multiClick(ActionEvent e)

It makes sure that on a double click only xxx_doubleClick is called and not xxx_singleClick also.

The same trick works with all events:

mybean_propertyChanged(PropertyChangeEvent e)
mylist_selectionChanged(...)
...

Tom 04/13/05 08:46:16 AM EDT

A cleaner solution (IMHO) are closures. Using closures would result in something like:

JButton button = new JButton();
button.addActionListener() { e | button.setText("bla"); }

Closures basically are inner classes that can access its context without having to use final (the local variable button is used in the inner class). Groovy provides a (hopefully soon) standard way to do this, but at least Groovy is fully Java compatible.

A Wolfe 04/12/05 11:21:22 AM EDT

Maybe I'm not following the argument here, but I guess I wonder why someone would prefer to pass around function pointers rather than interfaces. Can't the dispatch code just as easily invoke a method through an interface as through a Delegate class?

I guess I am uncomfortable with the modularity here. First of all, actual implementation classes have a sort of rigidity from the standpoint of the client and the programmer. So I like having interfaces anyway. But the other issue is that a method may start out being 'standalone', but then it may need to be called as part of a sequence of other methods. If you delegate through Interfaces, then it would seem you could add those other methods very easily.

Finally, variable argument lists are prone to incorrect use in all circumstances; but in this one there is no commonalties among the arguments. The classic 'printf' variety of variable argument lists was very clear -- each of the variable arguments is intended to be rendered as text. In this case it can be results of embedded function calls or anything. I guess I don't understand why one would want to suppress type checking.

Anyway I have really not gotten the idea or the benefit of this technique. Sometimes it's worthwhile to emulate one language's constructs in another language, but I don't see it here.

Ross Judson 04/12/05 09:08:06 AM EDT

There's nothing wrong with inner classes per se; they represent a superset of the functionality of delegates or method pointers. The problem is the Java language itself, and the lack of lightweight anonymous function/class declaration, and the lack the type inferencing. Fix those two things and the ugly part of inner classes (the declaration syntax) goes away.

Scala does lightweight functional syntax very nicely. If func takes something like an action listener, you can call it like this (for arrow read greater-equals):

func(event "arrow" event.getComponent().setSelected(true));

Scala knows the expected type for the call and builds the scaffolding necessary. Under the covers you end up with:

func(new ActionListener() {
public void actionPerformed(Event event) {
event.getComponent().setSelected(true)
}});

Michael Abernethy 04/11/05 01:01:16 PM EDT

The Buoy package contains some things similar to what you've outlined in your article. Although I have not worked with, reading the examples makes it appear that your goals of making the event handling code easier exists already in Buoy.

Kevin Timm 04/11/05 10:16:11 AM EDT

One of the things I miss the most about C is the lack of pointers to functions. Used correctly, these are fantastically useful. Hopefully, some of that can be added back (or implemented as is shown here) for the greater good of all.

Remember too, the 'Evil Empire' did not invent this desire (as noted by a previous respondent) they only implemented a shortcoming that they saw. This is not a bad thing.

Javanaut 04/11/05 07:15:38 AM EDT

### Dennis Farr commented ...
Great article. I have been haunted by the thought that not all differences between C# and Java were abberations, and your article shows how to take advantage of the good ideas coming out of the evil empire and use them inside Java. ###

The idea is certain to provoke widepsread discussion - it reminds how close C# and Java are.

Dennis Farr 04/10/05 01:23:31 PM EDT

Great article. I have been haunted by the thought that not all differences between C# and Java were abberations, and your article shows how to take advantage of the good ideas coming out of the evil empire and use them inside Java. Java is at least open enough to discuss and use ideas from outside Sun, as I hope yours will be.