Movatterモバイル変換


[0]ホーム

URL:


Wayback Machine
205 captures
10 Feb 1999 - 16 Jan 2026
MayJUNJul
27
201120122013
success
fail
COLLECTED BY
Organization:Alexa Crawls
Starting in 1996,Alexa Internet has been donating their crawl data to the Internet Archive. Flowing in every day, these data are added to theWayback Machine after an embargo period.
Collection:Alexa Crawls
Starting in 1996,Alexa Internet has been donating their crawl data to the Internet Archive. Flowing in every day, these data are added to theWayback Machine after an embargo period.
TIMESTAMPS
loading
The Wayback Machine - https://web.archive.org/web/20120627043929/http://java.sun.com:80/docs/white/delegates.html
Skip to ContentSunJavaSolarisCommunitiesMy SDN Account
SDN Home >Products & Technologies >Java Technology >Reference >White Papers >
 
White Paper

About Microsoft's "Delegates"

 


The JavaLanguage Team
JavaSoft, Sun Microsystems, Inc.

Introduction
Inner Classes vs. Method References
Adapter Objects and Delegation
-Example: A clickable button
-Example: Sorting an array
-What about multicast?
Performance Issues
-Sidebar:Implementing delegates using reflection
-Application footprint
Conclusion

The newest version of the Microsoft Visual J++ developmentenvironment supports a language construct calleddelegates orbound method references. This construct, and the new keywordsdelegate andmulticast introduced to support it,are not a part of the Java programminglanguage, which is specified by theJava LanguageSpecification and amended by theInnerClasses Specification included in thedocumentation for theJDK 1.1 software.

It is unlikely that the Java programming language will everinclude this construct. Sun already carefully consideredadopting it in 1996, to the extent of building and discarding workingprototypes. Our conclusion was that bound method references areunnecessary and detrimental to the language.This decision was made in consultation with Borland International,who had previous experience with bound method references in Delphi Object Pascal.

We believe bound method references areunnecessary because anotherdesign alternative,inner classes, provides equal or superiorfunctionality. In particular, inner classes fullysupport the requirements of user-interface event handling, and havebeen used to implement a user-interface API at least as comprehensiveas the Windows Foundation Classes.

We believe bound method references areharmful because they detractfrom the simplicity of the Java programming language and thepervasively object-oriented character of the APIs. Bound methodreferences also introduce irregularity into the language syntax andscoping rules. Finally, they dilute the investment in VM technologiesbecause VMs are required to handle additional and disparate types ofreferences and method linkage efficiently.

Return to Top

It has been clear from the outset that the original language neededsome equivalent of method pointers in order to support delegation and"pluggable" APIs. James Gosling noted this in his keynote at thefirst JavaOne conference. The keydesign question at the time was whether we needed a specializedfunction pointer construct, or whether there was some new way to useclasses to meet the requirements.

In the summer of 1996, Sun was designing the precursor towhat is now the event model of the AWT and the JavaBeans component architecture. Borland contributedgreatly to this process. We looked very carefully at Delphi ObjectPascal and built a working prototype of bound method references inorder to understand their interaction with the Java programminglanguage and its APIs.

Working through the implementation of bound method referencesshowed us how foreign they are to a pure object-oriented model. Wediscovered the following limitations:

  • Bound method references add complexity. The type systemmust be extended with an entirely new kind of type, the bound methodreference. New language rules are then required for matchingexpressions of the form `x.f' to method referenceconstructors, most notably for overloaded or static methods.
  • They result in loss of object orientation. Because oftheir special role and supporting syntax, bound method references are"second-class citizens" among other reference types. For example, while delegate types in Visual J++ are technically classes, they cannot extendclasses chosen by the programmer, nor implement arbitrary interfaces.
  • They are limited in expressiveness. Although bound methodreferences appear to the Java VM as reference types, they are no moreexpressive than function pointers.For example, they cannot implement groups of operations or containstate, and so cannot be used with Java class library iteration interfaces.We wanted the Java language to beclass-based, in which classes doall the work, rather than supplyingfunction pointers as an alternate and redundant way to perform the samedelegation tasks.
  • They are no more convenient than adapter objects. Althoughour analysis indicated that some code examples could be expressed moreconcisely with a specialized method reference syntax, we also found thatthe additional notational overhead for inner classeswas never more than a handful of tokens.

Although a native code compiler like Delphi Object Pascal canimplement bound method reference calls with a couple of instructions,there is no comparably efficient way to implement them on anunmodified Java VM. Our prototype therefore used compiler-generatedadapter classes. This solution was fast, but pointed to an evenbetter solution -- improving support for adapter objects of all kinds.

With these results in hand, the designers of the Java programminglanguage decided to introduce inner classes. Inner classes,especially anonymous inner classes, make it possibleto create and use adapter objects as easily as bound method references,while retaining all of the benefits of a uniformly class-based solution.

Return to Top

We have argued above that adapter objects, using inner classes, are abetter solution than bound method references. Let's now take a lookat adapter objects in action. We will examine two cases from the Javaplatform APIs, contrasting the solution we adopted with an alternativebased on method references.

Return to Top

Programs that use delegation patterns are easily expressed with innerclasses. In the AWT event model, user-interface components send eventnotifications by invoking methods of one or more delegate objects thathave registered themselves with the component. A button is a verysimple GUI component that signals a single event when pressed. Hereis an example using theJButton class from the Swing toolkit:

public class SimpleExample extends JPanel {  JButton button = new JButton("Hello, world");      System.out.println("Hello, world!");    }  ...  public SimpleExample() {    add(button);    ...  }  ...}

When the user clicks on the button, it invokes theactionPerformed method of its delegate, which can be ofany class that implements theActionListener interface.

In a language that uses bound method references, the correspondingcode would be quite similar. Again, a button delegates a click to anaction method. In this case, the delegate is an enclosing object.Keeping the identifiers the same to make the remaining differencesstand out clearly:

public class SimpleExample extends JPanel {  JButton button = new JButton("Hello, world");    System.out.println("Hello, world!");  }  ...  public SimpleExample() {    add(button);    ...  }  ...}

The key conclusion is quite simple:Any use of a bound methodreference to a private method can be transformed, in a simple andpurely local way, into an equivalent program using a one-memberprivate class. Unlike the original, the transformed program willcompile under any JDK 1.1-compliant Java compiler.

Method references require the programmer to flatten the code of theapplication into a single class and choose a new identifier for eachaction method, whereas the use of adapter objects requires theprogrammer to nest the action method in a subsidiary class and choosea new identifier for the class name. In terms of program complexity, thedifference is four extra tokens and some indentation for theadapter-object pattern -- a negligible difference.

It is sometimes more convenient for the programmer to use ananonymous inner class. Anonymous classes make the code using anadapter object as short as the code using a method reference. Thoughit requires the same number of tokens as a method reference,an anonymous adapter object avoidsthe need for an extra identifier by nesting the action method directlywithin the expression that attaches it to the button:

public class SimpleExample extends JPanel {  JButton button = new JButton("Hello, world");  ...  public SimpleExample() {        System.out.println("Hello, world!");      }    add(button);    ...  }  ...}

Note that this style of event configuration puts the button event methodas close as possible to the initialization of the button. By contrast,when named classes or methods are used, the event method can end up faraway from the initialization, because it must be placed in the enclosingclass, and must be mixed with other event methods for the same panel.

With either kind of delegate, whether an adapter object or a methodreference, the programmer is free to ignore the separate identity ofthe delegate object and regard it as an integral part of the panelclass, i.e.,SimpleExample. The action method is free ineither case to access private members of the panel class, because itis in all cases nested inside the implementation of that class.

Return to Top

Adapter objects also find natural uses in non-GUI APIs. For example,the JDK 1.2 class libraries provide a routine for sorting an array of objects. Theroutine takes an argument that lets the programmer specify how tocompare the array elements. This argument, called acomparator,is an object with a method that is invoked by the sort routine to comparepairs of array elements. It is of the following type:

public interface Comparator {  public int compare(Object o1, Object o2);}

As an interface,Comparator can have any implementationwhatever. It is often most conveniently a local classor even an anonymous one, as in this examplewhere an array of strings is sorted in a case-insensitive manner:

void sortIgnoreCase(String words[]) {      String s1 = ((String)o1).toLowerCase();      String s2 = ((String)o2).toLowerCase();      return s1.compareTo(s2);    }  ...}

Since we used an anonymous class, the comparison method is placed withinthe call to the sort routine, where it is used just once.If the delegate were created with a boundmethod reference, the sort routine would have to be given a unique nameand placed in the body of the enclosing class, possibly far fromits actual point of use:

  String s1 = ((String)o1).toLowerCase();  String s2 = ((String)o2).toLowerCase();  return s1.compareTo(s2);}...void sortIgnoreCase(String words[]) {  ...}

Note also that the bound method reference in this case includes aspurious reference to the enclosing class, which is not actually usedby the algorithm. If the delegate outlives theenclosing object this feature can cause unexpected storage retention.More generally, it is poor program organization to place this methodin the enclosing class because it does not operate on the class. Allthese problems stem from the relative inflexibility of bound methodreferences as compared to inner classes.

Storage retention is not a problem with the local adapter object.Since the object does not actually use all the values visible to it(likethis orwords), the JDK 1.1 compiler doesnot incorporate them into the object as unnecessary references.

Return to Top

The Visual J++ delegate construct provides a convenient multicastfacility whereby a single delegate object can serve as a containerfor several other delegates, and "fan out" calls to it. SinceMicrosoft WFC components internally multicast their events (as doesSwing), there is little occasion for clients to directly combinedelegates. This feature appears to be intended to make it easier tocreate new event types and new components which multicast them.

When implementing new event types in the Swing toolkit, a componentauthor may use theEventListenerList class to managelists of event handlers. Code usingEventListenerList isslightly more verbose than the corresponding code relying on theVisual J++ compiler support for multicasting. On the other hand,coding multicast in the standard Java language is more straightforwardand less "magical." This approach is also more easily modified to createvariations of the basic event notification procedure, such as runningboolean-valued event handlers until one returns true, or adding up theresults produced by integer-valued event handlers.

Moreover, the cost model for multicasting in a program written in theunadulterated Java language is easier to understand and (if necessary) modify.For example, each additional listener in a Swing component occupiesexactly two additional words, and a component with no listeners usesno storage for the absent listeners. Instead of a one-size-fits-allmulticast mechanism, Swing designers and extenders are free to usewhichever data structure best fits the application.

Return to Top

Looking "under the hood," it is easy to understand our conclusion that anyimplementation of bound method references will either be inefficientor non-portable.

A portable implementation of delegates that generates code capable ofrunning on any compliant implementation of the Java platform wouldhave to rely on the standard Java Core Reflection API. Everybound method reference would then include an embedded object of typejava.lang.reflect.Method to refer to the target method. Thisobject, counting its three unshared subobjects, occupies over 30 words ofstorage (assuming 2 words per object header, and subject to variabilitywith the length of the method name). Thus, the Visual J++ bound methodreferences, if they use reflection, must be an order of magnitude heavierthan Delphi Object Pascal method references. Moreover, each call to abound method reference must go through the reflectiveMethod.invoke protocol, which requires that arguments bepackaged up inside anObject array, and additional wrappersand casts for primitive arguments and return values. (Thesidebar contains a detailed example.)

Thus, every call to a delegate of typeint(int,int) requires creation of threeInteger objects and a two-elementObjectarray, for a total of 14 words of heap allocation. This cost willmake programmers hesitate to use bound method references for frequentoperations, since calls to adapter objects always run at full speed.

Of course, a VM and its JIT could recognize these uses of reflectiveoperations as special cases and inline away the allocations. However,the engineering effort required to implement such clever optimizationsis much better spent making all kinds of objects faster and lighter.It is at this point that an aesthetic objection to adding redundantfeatures to the language design solidifies into a real-world productengineering issue.

In the most extreme case, a compiler and VM might avoid reflectionaltogether in favor of special native methods.While a highly efficient implementation is achievable in this way,such a strategy immediately precludes portability to compliantimplementations of the Java platform. This is a serious objection,as it abandons the core value proposition of the Java platform:"Write once, run anywhere."

Return to Top

The proponents of bound method references have made much of theproliferation of classes that are created when adapter classes are usedextensively. They claim that these large numbers of classesthreaten an excessive enlargement of the application footprint.In evaluating these claims, it is important to understand that adapterclasses are not inherently costly. The code for the methods withinthese classes would be needed even if method references were used.The cost increment is almost entirely due to overhead imposed by aclass file format that was designed prior to the introduction of innerclasses. As a result, much information is replicated for each innerclass that could in principle be shared.

For example, the classes under the packagejava.awt.swingoccupy about 3 megabytes of storage in about 1200 class files.Constant pools account for 59 percent (1.8 megabytes) of this size.Among the anonymous inner classes in this same group, fully 75 percentof the on-disk size, or 611 bytes on average, is devoted to constant pools.(Note: Unlike delegates, 30% of these anonymous classes have twoor more methods, so an exact comparison with delegates is difficult.)

Sun chose to implement inner classes in a manner that wascompatible with the existing VM. This preserved the investmentthat our licensees and their customers have made in Java technology.However, the Java platform is still evolving. From the very introductionof inner classes, Sun has considered eventual extensions totheJAR or class file formats that would make smallinner classes very inexpensive, because of sharing of constantpools and other data.

It is also important to note that the in-memory footprint of anapplication is not constrained by compatibility considerations. A VMis free to introduce alternative in-memory representations, asexemplified by the on-the-fly translation to machine code performed bycurrent high-performance VMs.Newer versions of Sun's VM share information between constant pools,so that the total size of the class files, "flattened" as they are,is a misleading indicator of memory footprint.

It is clear, then, that efforts toreduce application footprint are best directed toward creating evenmore efficient Java VMs, not changing the language. Suchimprovements will benefit all programs, not only those making use ofdelegation, and will do so without compromising the simplicity andelegance of the Java programming language.

Return to Top

Many of the advantages claimed for Visual J++ delegates -- typesafety, object orientation, and ease of component interconnection --are simply consequences of the security or flexibility of the Javaobject model. These advantages are routinely enjoyed by allprogrammers using the Java language, without resorting to non-standardlanguage syntax or platform-specific VM extensions.

Bound method references are simply unnecessary. They are not partof the Java programming language, and are thus not accepted bycompliant compilers. Moreover, they detract from the simplicity andunity of the Java language. Bound method references are not theright path for future language evolution.

Oracle is reviewing the Sun product roadmap and will provide guidance to customers in accordance with Oracle's standard product communication policies. Any resulting features and timing of release of such features as determined by Oracle's review of roadmaps, are at the sole discretion of Oracle. All product roadmap information, whether communicated by Sun Microsystems or by Oracle, does not represent a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. It is intended for information purposes only, and may not be incorporated into any contract.



About Sun  | About This Site  | Newsletters  | Contact Us  | Employment  | How to Buy  | Licensing  | Terms of Use  | Privacy  | Trademarks
 

 
© 2010, Oracle Corporation and/or its affiliates

Unless otherwise licensed, code in all technical manuals herein (including articles, FAQs, samples) is provided under thisLicense.
 
XML Sun Developer RSS Feeds

[8]ページ先頭

©2009-2026 Movatter.jp