PROPOSAL: Named method parameters

Reinier Zwitserloot reinier at zwitserloot.com
Wed Apr 22 17:39:51 PDT 2009


rt.jar indeed does not include paramnames.

Compiling and jarring all of it gives you 13MB without any debug info,  
and 15MB when including all local variables (there's no easy way to  
compile with just argnames (or, better yet, argnames for non-private  
methods), stil, that's quite a change, so consider the semi-proposal  
revoked. (Though, it does help support my earlier pre-proposal where  
source files explicitly declare a method to be accessible via named  
parameter call).

  --Reinier Zwitserloot
Like it? Tip it!
http://tipit.to



On Apr 21, 2009, at 17:36, Joseph D. Darcy wrote:

> Catching up on responses, as has been further discussed on the list
> recently, requests in this general vein have been considered before in
> JDK 6.  While there are certainly use-cases this facility could  
> clarify,
> I remain unconvinced of the cost/benefit ratio of this proposal.
>
> A few design notes, a single @PublicParameterNames annotation with a
> boolean member could be used instead of a pair of "do it/don't do it"
> annotations.
>
> A full proposal for this facility would need to deal with the cases
> where the number of parameters in the class file differs from the  
> number
> of parameters in the source code, a situation already mildly exposed
> when calling toGenericString on some Method and Constructor objects.
>
> Not supporting parameter reordering greatly simplifies the proposal by
> leaving method selection largely unaffected, but also seems to limit  
> the
> usefulness of the proposal.  If the main benefit is just seeing the
> parameter name in the program text; can't the IDE do that?
>
> I'd isn't clear to me how @PublicParameterNames would interact with
> overridden methods in class hierarchies.  Presumably the names of the
> static type of the call site would need be match, even though the
> runtime type could differ.  If a subclass overrode a method and  
> changed
> its parameter names (which currently has no affect on compatibility),
> the subclass would no longer be substitutable for the parent class,
> which would break a fundamental design principle.
>
> At least there is no binary compatibility impact since the names would
> only be checked at compile time and binary compatibility is about
> preserving the ability to link.
>
> -Joe
>
> Paul Martin wrote:
>> I'd like to propose the implementation of optionally named method
>> parameters, and suggest that they are particularly useful when  
>> creating
>> immutable objects (which are important in our increasingly concurrent
>> world).
>>
>> Note that this is a topic that seems to have been considered before  
>> (see the
>> note in http://paulhammant.com/blog/announcing_paranamer.html which  
>> suggests
>> that it was even considered for Java 6), but I can't see it in the  
>> current
>> list of Java 7 changes or in the Project Coin mailing list archives  
>> (though
>> others have also discussed it in relation to Java 7, such as Alex  
>> Miller in
>> http://tech.puredanger.com/2007/08/15/dr-java7/ and
>> http://tech.puredanger.com/2007/10/11/java7-roundup-32/).   
>> Therefore I am
>> proposing it here - I think that it is an important change (unless  
>> anyone
>> can suggest how I can reasonably create an immutable object with  
>> four or
>> more properties without using a Builder or a list of unnamed  
>> parameters).
>>
>> Also note that other relevant references include:
>> http://blogs.sun.com/abuckley/entry/named_parameters (which  
>> discusses why
>> parameter reordering might be difficult),
>> http://beust.com/weblog/archives/000096.html (which suggests that  
>> we do not
>> need named parameters, but really just shows the use of the Builder  
>> pattern
>> which has limitations).
>>
>>
>> Named method parameters
>>
>> AUTHOR(S):
>>
>> Paul Martin
>>
>> OVERVIEW
>>
>> FEATURE SUMMARY:
>>
>> Named parameters allow a method or constructor caller to explicitly  
>> state
>> the parameter name of each parameter value passed to the method or
>> constructor.  Without named parameters, only the order of the  
>> parameter
>> values is significant (and it may not be clear what each value  
>> represents).
>>
>> MAJOR ADVANTAGE:
>>
>> This is a relatively simple way of introducing named parameters to  
>> the Java
>> platform.
>>
>> MAJOR BENEFIT:
>>
>> Named parameters allow method calls with relatively long lists of  
>> parameters
>> (greater than 3) to be understood by developers.  This can also  
>> facilitate
>> the direct use of constructors and factory methods to create  
>> immutable
>> objects, where otherwise Builders or mutable JavaBeans would be  
>> required.
>>
>> MAJOR DISADVANTAGE:
>>
>> The syntax for method calls would change to allow both named and  
>> unnamed
>> parameters to be used.
>>
>> Named parameters might be used too often, which could unnecessarily  
>> clutter
>> source files.
>>
>> Metadata to store the names of the parameters must be added to  
>> classfiles
>> (for example as annotations).
>>
>> The use of annotations to describe named parameters would mean that  
>> no
>> metadata would be stored about the parameter names used by the method
>> caller, and so no runtime checks to match the parameter names being  
>> used
>> could be made (only compile-time).  If the parameter names change  
>> (but
>> otherwise the method signature does not), then the method caller  
>> would not
>> be aware of the changes until it was recompiled.  Note that this is  
>> existing
>> behaviour for unnamed parameters, and would only be a problem if  
>> the meaning
>> of the parameters also changes (which should indicate that the  
>> caller would
>> need to change anyway, but this would not be detected automatically  
>> at
>> runtime).
>>
>> ALTERNATIVES:
>>
>> Unnamed parameters can make the same method calls as named  
>> parameters, but
>> if there are many parameters they are harder to understand and  
>> prone to
>> ordering-related bugs (particularly for primitive types or Strings).
>>
>> The Builder pattern can be used to simulate named parameters in
>> constructors/factory methods.  For example the following class uses a
>> Builder to initialise itself (note that only two properties are  
>> used to
>> simplify the example):
>>
>>    public final class MyClass {
>>
>>        private final String name;
>>        private final int age;
>>
>>        private MyClass(Builder b) {
>>            this.name = b.name;
>>            this.age = b.age;
>>        }
>>
>>        public static class Builder {
>>
>>            private String name;
>>            private int age;
>>
>>            /**
>>             * Name to set.
>>             */
>>            public Builder setName(String name) {
>>               this.name = name;
>>               return this;
>>            }
>>
>>            /**
>>             * Age to set
>>            */
>>            public Builder setAge(int age) {
>>                this.age = age;
>>                return this;
>>            }
>>
>>            public MyClass build() {
>>               return new MyClass(this);
>>            }
>>        }
>>    }
>>
>> Objects can then be constructed in the following manner:
>>
>>    MyClass obj = new  
>> MyClass.Builder().setName("Fred").setAge(53).build();
>>
>> However, the use of a builder requires additional code, and all  
>> parameters
>> are effectively optional from the perspective of the compiler (it  
>> cannot
>> easily check that all of the required setter methods have been  
>> called), so
>> bugs may occur where parameter values are not set.  Note that  
>> runtime checks
>> can be made to ensure that all property values are set, but they  
>> involve
>> additional work and cannot be used by the compiler (though static  
>> analysis
>> of the code in conjunction with annotations might be able to repeat  
>> many of
>> these checks).
>>
>> There are also many ways to implement named parameters that are  
>> different to
>> the solution proposed here.  These include:
>>
>> Implement optional named parameters on all methods:  This avoids  
>> the need
>> for the @PublicParameterNames annotation, but may mean inconsistent  
>> usage of
>> named parameters - the annotation is also a suggestion for the use  
>> of named
>> parameters by the caller (which IDEs can also make use of).  This  
>> will also
>> highlight the difference to classfiles compiled with earlier  
>> versions of
>> Java, where named parameters cannot be used at all (since it will  
>> then not
>> be obvious when named parameters can and cannot be used).
>>
>> Add parameter names to the classfile as 'fundamental' method  
>> metadata rather
>> than as annotations: This may allow closer integration of the named
>> parameters with the rest of the language, but its impact on the  
>> rest of the
>> language (and JVM) is much greater.  The same inconsistencies and
>> incompatibilities described in the previous alternative would also  
>> apply.
>> In addition, the use of annotations should not preclude the  
>> subsequent
>> modification of classfiles in a later release - the annotations  
>> could still
>> remain (at a potential cost of some duplication).
>>
>> EXAMPLES
>>
>> SIMPLE EXAMPLE:
>>
>> Constructor declaration:
>>
>>    @PublicParameterNames
>>    public MyClass(String name, int age) { ....
>>
>> Constructor use:
>>
>>    MyClass obj = new MyClass(name: "Fred", age: 53);
>>
>> ADVANCED EXAMPLE: Show advanced usage(s) of the feature.
>>
>> The full class definition from the simple example is shown below,  
>> as a
>> contrast to that provided in the Builder example.
>>
>>    public final class MyClass {
>>
>>        private final String name;
>>        private final int age;
>>
>>        /**
>>         * @param name Name to set
>>         * @param age Age to set
>>         */
>>
>>        @PublicParameterNames
>>        public MyClass(String name, int age) {
>>            this.name = name;
>>            this.age = age;
>>        }
>>    }
>>
>> DETAILS
>>
>> SPECIFICATION:
>>
>> The @PublicParameterNames annotation is used on a constructor or  
>> method to
>> allow named parameters to be used when calling it.  It can also be  
>> applied
>> to a class or package to apply to all methods within.  Similarly, a
>> @NoParameterNames annotation can be used on a constructor, method,  
>> or class
>> to override the use of @PublicParameterNames at a higher level.
>>
>> The compiler can then automatically generate a
>> @PublicParameterName(value="parameter-name") annotation for each  
>> affected
>> method.  These can then be used by the compiler (and IDE) to  
>> validate the
>> parameter names used by callers of the method or constructor.
>>
>> The use of parameter names by callers is always optional (primarily  
>> for
>> backwards compatibility).  However, parameter names cannot be used  
>> for some
>> parameters and not others (this would make the code harder to read).
>>
>> Parameters must always be specified in the same order regardless of  
>> whether
>> parameter names are used - parameter reordering by callers is not  
>> allowed
>> (reordering would make overloading difficult, and is not really  
>> necessary).
>>
>> Inheritance: Neither the @PublicParameterNames annotation (and
>> @NoParameterNames annotation), or the names of the parameters  
>> themselves,
>> need to be inherited.  This is because only static evaluation of a  
>> caller's
>> parameter names will be applied (rather than at runtime), so the  
>> callers
>> parameter names only need to match those of the declared type of the
>> target.  However, it would still be advisable to reuse the same  
>> parameter
>> names and annotations when overriding a method (IDEs could help  
>> with this).
>>
>> COMPILATION:
>>
>> The compiler must automatically generate a
>> @PublicParameterName(value="parameter-name") annotation for each  
>> method and
>> constructor annotated with @PublicParameterNames (or whose the  
>> parent class
>> or package is annotated with @PublicParameterNames and the child  
>> class or
>> method does not override it with @NoParameterNames).
>>
>> For example:
>>
>>    int myMethod(int param1, String param2)
>>
>> Would effectively become:
>>
>>    int myMethod(@PublicParameterName("param1") int param1,
>> @PublicParameterName("param2") String param2)
>>
>> Method-calling syntax would need to change, using a colon to  
>> separate the
>> parameter name and value where the are used.  For example:
>>
>>   MyClass obj = new MyClass(name: "Fred", age: 53);
>>
>> When a method caller uses parameter names, the compiler must check  
>> that
>> those parameter names exactly match the value of generated
>> @PublicParameterName annotations of the target method or  
>> constructor.  It is
>> a compilation error if they do not match or the target method or  
>> constructor
>> does not have named parameters.
>>
>> IDEs can use the @PublicParameterNames and @NoParameterNames  
>> annotations (or
>> @PublicParameterName directly) to automatically insert the relevant
>> parameter names as part of code-completion.  Additional refactoring  
>> support
>> would also be required to enable parameter names to be renamed, or  
>> added and
>> removed completely.
>>
>> Frameworks such as Spring can use the same annotations to allow  
>> objects to
>> be created from their configuration files using named parameters to
>> constructors and factory methods.  Currently they only allow  
>> objects to be
>> created from configuration files as JavaBeans (with setter methods)  
>> or with
>> ordered (and unnamed) parameters.
>>
>> TESTING:
>>
>> The feature can be tested by compiling and running programs that  
>> exercise
>> the feature.
>>
>> LIBRARY SUPPORT:
>>
>> No.
>>
>> REFLECTIVE APIS:
>>
>> java.lang.reflect.Method and java.lang.reflect.Constructor could be  
>> enhanced
>> with new methods that return parameter names.  However, that is not  
>> required
>> to successfully implement the proposal.
>>
>> OTHER CHANGES:
>>
>> No.  The use of named parameters is always optional.  The javadoc  
>> tool
>> already documents parameter names.  Other tools/libraries might  
>> benefit from
>> these changes, but their use is not required.
>>
>> MIGRATION:
>>
>> The @PublicParameterNames annotation (and @NoParameterNames  
>> annotation)
>> simply needs to be added to the appropriate methods.  IDEs could then
>> suggest the use of parameter names for the method's callers, and  
>> apply the
>> changes automatically.
>>
>> COMPATIBILITY
>>
>> BREAKING CHANGES:
>>
>> No.
>>
>> EXISTING PROGRAMS:
>>
>> The changes required by this feature should be transparent to  
>> existing
>> source and class files if annotations are used internally to  
>> describe the
>> named parameters.  I am not sure what the impact would be otherwise.
>>
>> REFERENCES
>>
>> EXISTING BUGS:
>>
>> 4124331 (though it is set to 11-Closed, Will Not Fix, request for
>> enhancement, and from 1998)
>>
>>
>
>




More information about the coin-dev mailing list