PROPOSAL: Static Methods in Interfaces (v1.1)

Reinier Zwitserloot reinier at
Tue Mar 17 18:59:38 PDT 2009

Includes Joe D'Arcy's suggestions. An easier to read copy with markup  
is available at:

The text below is identical aside from the formatting:

   PROPOSAL: Static Methods in Interfaces


     This is version 1.1.
     The latest version can be found at

     Changes from v1.0 to v1.1: Added links to bug reports on, expanded on alternatives, simplified reflective APIs,
     added note on javadoc. (via Joe D'Arcy).


     Reinier Zwitserloot
     Roel Spilker



         Static methods are now allowed in interfaces. The static method
         is defined with a method body in the interface and it exists in
         the namespace of the interface; it does not imply that
         implementing classes must implement the method. This feature is
         especially useful for utility methods that belong with a given
         interface. For example, many methods in java.util.Collections
         are specific for a particular interface, such as sort
         (java.util.List) and unmodifiableMap (java.util.Map).


         Allows maintaining code that 'goes together' in a single file,
         and helps auto-complete dialogs come up with more relevant
         operations on any given object. Also improves syntax by using a
         more specific term (e.g. List) instead of a usually somewhat
         generic grab bag utility class (e.g. Collections). Also allows
         interfaces to contain pseudo-constructor, for common tasks and
         default implementations (e.g. could  
contain a
         method to create a new one based on a file extension). This
         proposal will also offer an easy solution to the current
         deplorable situation that you need to call on 2 separate  
         classes, one of which has no relation to List whatsoever, just
         to create an immutable List:
         Collections.unmodifiableList(Arrays.asList(items)) can be
         replaced with the much more elegant List.of(items)


         Java (the language) is very strictly namespaced; the default
         package is discouraged and java does not allow dynamically
         adding or changing methods at runtime (so called monkey
         patching). Java also does not support mixins nor multiple
         inheritance. Therefore, the platform currently lacks a way to
         meaningfully offer utility methods for interfaces. Instead,
         kludges such as java.util.Collections exist as a vehicle for
         these support methods. Furthermore, static methods in  
         are currently illegal (see JLS Chapter 9.4
         so this proposed change does not complicate the language very  


         Confusion about the notion that static methods in java in java
         are not 'virtual' (they are not inherited and cannot be
         overridden) may cause a programmer to erroneously think a  
         method in an interface implies it is something an implementing
         class must implement. However, the mandatory method body should
         help avoid confusion. Slightly more complex language
         specification. No opportunity to use the static keyword in
         interfaces for some sort of /factory interface/ concept (an
         interface for constructors and static methods). The proposed
         implementation is also somewhat inconsistent in rare cases
         compared to static methods in classes. While this inconsistency
         is a disadvantage, the authors do not believe there's a way to
         avoid this inconsistency without creating more serious  


         The usual solution to this problem right now is to offer a
         separate utility class (a class that is not instantiable and
         contains only static methods) that contain the utility methods,
         along with a reference in the /javadoc/ of the interface to  
         utility class. For example, java.util.Collections is the  
         class that goes with Map, List, Set and other Java Collections
         API interfaces. The use case of default / common  
         is currently handled by having an implementing class with a
         constructor. For example, a new class called could be made that takes a String
         and implements FileFilter. The sugar employed by this proposal
         is itself also an alternative: Creating a member type class  
         contains the static methods (With just a backwards and  
         compatible API addition, you could make List.Utils.of(items)
         work in java 1.6 notation (The Utils class is an inner member
         type to the interface, which is legal, and as it is a class,  
         contain static methods.

         Another language change that can serve as an alternative is
         extension methods (the ability to lexically 'monkey patch'
         methods onto types, such as "import static
         java.util.Collections.sort into java.util.List;"



         public interface Foo {
             public static void printHello() {
                 System.out.println("Hello, World!");

         Foo.printHello();  //Prints 'Hello, World!


         package java.util;

         public interface List<E> extends Collection<E> {
             int size();
             // List's other instance methods

             public static <T> List<T> of(final T... items) {
                 return new AbstractList<T>() {
                     public T get(int index) {
                         return items[index];

                     public int size() {
                         return items.length;

         List<String> list = List.of("foo", "bar");
         assert list.get(0).equals("foo");
         assert list.size() == 2;



         Java Language Specification changes:

         JLS Chapter 9.1.4




         JLS Chapter 9.4

             Every method declaration in the body of an interface is
             implicitly abstract, so its body is always represented by a
             semicolon, not a block.


             Every non-static method declaration in the body of an
             interface is implicitly abstract, so its body is always
             represented by a semicolon, not a block.


             Note that a method declarated in an interface must not be
             declared static, or a compile-time error occurs, because
             static methods cannot be abstract.


             None - this line is removed from the JLS.

         JLS Chapter 9.5
 > and
         are bumped to 9.6 and 9.7, respectively, and a new 9.5 is  

             9.5 Static Method Declarations

              StaticMethodModifiers TypeParameters_opt  ResultType
             MethodDeclarator Throws(opt)  ;

              MethodModifiers static
              static MethodModifiers

         The MethodModifiers are described in 8.4.3
         The access modifier |public| is discussed in 6.6
         A compile-time error occurs if the same modifier appears more
         than once in an static method declaration. The static keyword  

             Static method declarations in interfaces are either public
             or private; protected and package private are not allowed.
             If no access modifier is specified, the static method is
             implicitly public, to be consistent with the notion that
             everything else in an interface, be it a field, an abstract
             method, or a member type, is implicitly public. Private
             static methods are allowed to accommodate helper
             methods. Other than being limited to public and private
             access, a static interface method is identical to a method
             declaration in a class (8.4)
             During compilation, all static methods are stored in a
             synthetic inner class called $Methods, which is generated
             with a private constructor. If that class already exists in
             the source file, a compile-time error occurs.


         JLS Chapter 15.12.1

         The specification of method invocation forms that invoke static
         methods are updated to refer to 'class or interface' instead of
         just 'class', and the following line:

             If /TypeName/ is the name of an interface rather than a
             class, then a compile-time error occurs, because this form
             can invoke only |static| methods and interfaces have
             no |static| methods.

         is replaced with:

             If /TypeName/ is the name of an interface rather than a
             class, then the call is presumed to be for a static method
             in a synthetic member class of the interface, called
             $Methods. If the method exists, the class to be searched is
             denoted by /TypeName.$Methods/ where /$Methods/ is a static
             inner class of the interface /TypeName/, literally called


         Any interface with static methods is sugared by creating a
         member class called $Methods which will contain the static
         methods. The generated $Methods class should also have a  
         constructor, as they aren't supposed to be instantiable. If the
         $Methods inner class has been explicitly created in the source
         file, any static methods in the interface are considered a
         compile-time error (if the class is present in the source file,
         the assumption is that the programmer wants to keep manual
         control of the static methods). For method invocations,
         currently, an invocation of the form InterfaceName.method(),
         will result in an immediate compile error. The compiler will
         instead need to search the $Methods class (if any exists) for
         the method, and rewrite the call to
         InterfaceName.$Methods.method() if the method does exist in the
         $Methods inner class.

         The method is not inherited by any member types. So, the second
         'hello()' call in the following example would result in a
         compile time error (method not found):

             public interface Foo {
                 public static void hello() {
                     System.out.println("Hello, World!");

             public class Bar implements Foo {}

             Foo.hello(); //works
             Bar.hello(); //does not work

         This is an unfortunate inconsistency (if Foo was a class,
         Bar.hello() would work just fine), but there is no way to
         adequately recreate this inheritance system with syntax sugar.
         Even with a more thorough solution (that involves changing the
         JVM), allowing inheritance of the methods would mean allowing
         diamond relations (where 1 class implements 2 interfaces, that
         each have the same static method signature with different
         implementations. Which one is chosen?). This is principally the
         reason why this proposal suggests not letting the method be
         inherited. However, if inheritance is deemed important, the
         alternate solution is to fix the JVM Specification chapter 2.13
 > in
         similar ways as the JLS, and make static methods legal in
         interfaces. The Type.method() invocation would then require a
         much broader search and should give up with a compile-time  
         if a diamond relation is found, listing the conflicting
         implementations and asking the programmer to choose one.

         As this proposal breaks the norm on inheritance already, the
         following syntax is not allowed either, which for static  
         in classes *is* currently legal but flagged as a warning in all
         popular IDEs and code style checkers:

             Character c = 'f';
             c.isWhiteSpace(' '); //if Character was an interface, this
             would not be legal.


         This new feature can be tested by applying the existing tests
         for static method calls to static methods in interfaces.
         Compilation and class file parsing needs to be expanded to  
         tests to read method bodies in interfaces as well as classes.
         "Finding" the static method inside the $Methods inner class
         during compilation needs to be tested, which is straight
         forward. The changes described below to the reflective APIs  
         need testing, which is also straight forward.


         No library support is needed. However, it would be advisable to
         update various interfaces in the core java APIs with useful
         static utility methods. Some examples:

             * java.util.List/Map/Set: All methods in
               java.util.Collections should also be made available on  
               appropriate java collections API interface.
             * should contain a utility method
               'closeAndIgnoreException' (arguably better suited on
               InputStream instead).
             * java.util.List/Set: Should contain an 'of' method that
               makes unmodifiable lists and sets via varargs.
             * Should contain an
               'ofExtension(String)' method that creates a FileFilter  
               the provided extension.


         Currently, synthetic members are not treated specially by the
         reflection API. Therefore, this proposal does not require any
         reflective API changes. Attempting to use reflection to access
         these methods requires you to access them via the generated
         $Methods member. Asking for such a method's parent class would
         return the $Methods class, not the interface.


         The javadoc tool will need a minor change: It will need to
         produce a new section on static methods for interfaces, if they
         exist. (Unlike reflection, javadoc should abstract away the
         inner $Methods class). Fortunately, this code already exists  
         printing static methods in normal classes.


         No migration is needed. However, any java projects that
         currently employ utility classes (defined as having a private
         constructor that is not called anywhere in scope) which either
         return interface types, or take as first parameter an interface
         type, or both, where all previously mentioned interfaces are in
         the same package, are likely candidates for moving or copying  
         the relevant interface. Thus, IDEs can offer refactor advice to
         perform this task automatically and to find likely candidates.
         Such a refactor tool would for example identify all methods in



         Existing source that already uses an inner type named $Methods
         in an interface will change semantics when this proposal is
         implemented, primarily when queried via reflection. Between the
         vanishingly small odds of both a $Methods already existing and
         its methods being queried by the reflection API, and the  
         rule that $ should only be used in type names by compilers, the
         potential breaking change is hardly worth mentioning.


         Existing programs are not affected by this change, other than  
         described above in the 'breaking changes' section.


(Main RFE)

     URL FOR PROTOTYPE (optional):


More information about the coin-dev mailing list