Field and Method Literals

Brian Goetz brian.goetz at oracle.com
Tue Nov 22 10:24:32 PST 2011


> Ok, I didn't mean to start a whole crapstorm by asking.

You didn't start the crapstorm :)

You asked a reasonable "have you thought about" question, we responded 
"yes, we have thought about!", and we could have both gone away happy!

To be clear, there are three reasonable choices here:
  - Just don't ever support field literals;
  - Have a different syntax for field literals vs method literals;
  - Have the same syntax, and use a sensible heuristic for preferring 
one in the event of conflict.

The stupid choice would be:
  - Don't think at all about field literals now, and create a method 
literal syntax that boxes us in should we ever want field literals 
later, and then say "oh crap" later.

We won't be choosing that last choice.

> My only concern was that one of Brian's examples at Devoxx used a "::"
> operator with a lone symbol (I can't find the slide deck I saw right
> now, but a verison of it is available at
> http://www.parleys.com/#st=5&id=2170&sl=29):
> Person::getLastName
> This one is probably not such a great example to illustrate my point,
> as I think no one is going to name a field "getLastName".  This one is
> more reasonable (albeit still contrived):
> public class MyClosable { private boolean closed; public boolean closed();}
> If I use the expressionMyClosable::closed
> to which member am I referring?  With only method literal support in
> the language, then it's obviously the method, but with a full-blown
> reflection literal syntax, it would be ambiguous.
> All I'm saying is that the choice of method literal syntax should not
> make a future reflection literal syntax different.
> -matthew
> On Mon, Nov 21, 2011 at 6:03 PM, Brian Goetz<brian.goetz at oracle.com>  wrote:
>> My bad.  Next time I'll just not say anything.
>>
>> On 11/21/2011 6:47 PM, Neal Gafter wrote:
>>>
>>> Brian-
>>>
>>> I think we'd all feel more comfortable if we could review for ourselves
>>> /how /the issues have been considered by the expert group.  Oracle long
>>> ago promised to provide a public mailing list where subscribers could
>>> see the expert groups deliberations.  Hearing your periodic assurances
>>> that the expert group is on top of things doesn't really serve the same
>>> purpose.
>>>
>>> Cheers,
>>> Neal
>>>
>>> On Mon, Nov 21, 2011 at 2:35 PM, Brian Goetz<brian.goetz at oracle.com
>>> <mailto:brian.goetz at oracle.com>>  wrote:
>>>
>>>     You "caution the expert group to carefully consider the syntax",
>>> because
>>>     of possible ambiguities between features that are currently on the
>>>     requirements list (method refs) and features that are on various
>>>     people's wish list but not under active development (field refs).
>>>
>>>     I was merely saying we're well aware of these issues, so you can sleep
>>>     well knowing that they've already occurred to us and have been part of
>>>     the discussion, and that while field refs are not on our requirements
>>>     list, we realize that it would be stupid to inadvertently close the
>>> door
>>>     on them, and therefore have to be included in our analysis.
>>>
>>>
>>>
>>>     On 11/21/2011 4:59 PM, Matthew Adams wrote:
>>>      >  I'm not quite sure what that means.  Can you please elaborate?
>>>      >
>>>      >  On Mon, Nov 21, 2011 at 11:39 AM, Brian Goetz
>>>     <brian.goetz at oracle.com<mailto:brian.goetz at oracle.com>
>>>      >  <mailto:brian.goetz at oracle.com<mailto:brian.goetz at oracle.com>>>
>>>     wrote:
>>>      >
>>>      >       Don't worry, this road is already well explored.
>>>      >
>>>      >
>>>      >       On 11/21/2011 10:34 AM, Matthew Adams wrote:
>>>      >
>>>      >           I reiterate Chris's suggestion for method and field
>>> literals,
>>>      >           and caution
>>>      >           Project Lambda to carefully consider the syntax.  There is
>>> an
>>>      >           ambiguity
>>>      >           that I want to make sure that we're not overlooking here
>>> that
>>>      >           would cause
>>>      >           problems with various proposed method/field literal
>>> syntaxes.
>>>      >
>>>      >           Currently, Chris's examples and Project Lambda's "::" method
>>>      >           reference
>>>      >           syntax introduce an ambiguity when referring to a method
>>> that
>>>      >           has the same
>>>      >           name as a field.  See my post on this at
>>>      >
>>>
>>>   http://mail.openjdk.java.net/__pipermail/jdk8-dev/2011-__November/000293.html
>>>      >
>>>
>>>   <http://mail.openjdk.java.net/pipermail/jdk8-dev/2011-November/000293.html>
>>>      >           for
>>>      >           more detail on my suggestion.  In short, though, here's
>>>     the jist
>>>      >           (I'll use
>>>      >  "::", but I still prefer "#" as the method/field literal operator).
>>>      >             Consider the following class:
>>>      >
>>>      >           public class Foo {
>>>      >                private boolean close;
>>>      >                @Goo(hoo="loo") public Foo() { /* ... */ }
>>>      >                /* A */ public void close() { /* ... */ }
>>>      >                /* B */ public void close(int timeout) { /* ... */ }
>>>      >           }
>>>      >
>>>      >           If member literal syntax is to be supported now or in the
>>>     future,
>>>      >  "Foo::close" is ambiguous.  What should the compiler do here?
>>>      >             Interpret
>>>      >           the expression as a field or method reference if it's not
>>>      >           ambiguous?  I
>>>      >           think I'd prefer a syntax that requires parens for method
>>>      >           references:
>>>      >
>>>      >           Foo::close // field
>>>      >           Foo::close() // refers to method A above
>>>      >           Foo::close(int) // refers to method B above
>>>      >
>>>      >           This also allows me to refer to constructors, BTW:
>>>      >
>>>      >           Foo::()
>>>      >
>>>      >           And annotations:
>>>      >
>>>      >           Foo::()@Goo
>>>      >
>>>      >           And annotation properties:
>>>      >
>>>      >           Foo::()@Goo(hoo)
>>>      >
>>>      >           I reiterate also that the persistence specifications JDO&
>>>       JPA
>>>      >           can benefit
>>>      >           from such constructor, method&    field literals.  In their
>>>      >           absence, projects
>>>      >
>>>      >           like QueryDsl, Hibernate's Criteria, JPA's Criteria, and
>>>     JDO's
>>>      >           proposed
>>>      >           typesafe query APIs have been created, using generated
>>>     classes
>>>      >           to provide
>>>      >           the typesafe references that are needed.
>>>      >
>>>      >           -matthew
>>>      >
>>>      >
>>>      >           On Mon, Apr 18, 2011 at 3:40 AM, Chris
>>>     Beams<cbeams at vmware.com<mailto:cbeams at vmware.com>
>>>      >  <mailto:cbeams at vmware.com<mailto:cbeams at vmware.com>>>    wrote:
>>>      >
>>>      >               On Sun, Apr 17, 2011 at 8:14 PM, Collin
>>>     Fagan<collin.fagan
>>>      >               at gmail.com<http://gmail.com>  <http://gmail.com>>
>>>       wrote:
>>>      >
>>>      >               But more to the point what is Chris actually asking
>>>     for? Is
>>>      >               it just to be able to use static method references with
>>>      >               annotations?
>>>      >
>>>      >
>>>      >               This thread originated on coin-dev (thanks Rémi for
>>>      >               cross-posting here),
>>>      >               but I believe my original use case didn't make it
>>>     over.  Let
>>>      >               me reiterate
>>>      >               and expand.
>>>      >
>>>      >               Many will associate Spring with XML-based application
>>>      >               configuration, but
>>>      >               since Spring 3.0 we also offer a 100% Java-based
>>> solution
>>>      >               for configuring
>>>      >               dependency injection, application of advice, and the
>>>     myriad
>>>      >               other services
>>>      >               and features of the Spring container.  The central
>>>     artifacts
>>>      >               in this
>>>      >               support are user-defined "@Configuration classes".  A
>>>     brief
>>>      >               but practical
>>>      >               example follows to provide context for our use cases.
>>>      >
>>>      >               package com.myco.app.config;
>>>      >
>>>      >               import
>>>     org.springframework.context.__annotation.Configuration;
>>>      >               import org.springframework.context.__annotation.Bean;
>>>      >               import
>>>      >
>>>
>>>   org.springframework.jdbc.__datasource.embedded.__EmbeddedDatabaseBuilder;
>>>      >               import
>>>      >
>>>     org.springframework.jdbc.__datasource.embedded.__EmbeddedDatabaseType;
>>>      >               import
>>>      >
>>>
>>>   org.springframework.orm.__hibernate3.annotation.__AnnotationSessionFactoryBuilde__r;
>>>      >
>>>      >               import org.hibernate.SessionFactory;
>>>      >
>>>      >               import javax.sql.DataSource;
>>>      >
>>>      >               import com.myco.app.domain.Foo;
>>>      >               import com.myco.app.service.__FooService;
>>>      >               import com.myco.app.service.__SimpleFooService;
>>>      >               import com.myco.app.data.__FooRepository;
>>>      >               import com.myco.app.data.__HibernateFooRepository;
>>>      >
>>>      >               @Configuration
>>>      >               public class MyApplicationConfig {
>>>      >
>>>      >                    @Bean
>>>      >                    public FooService fooService() {
>>>      >               return new SimpleFooService(__fooRepository());
>>>      >                    }
>>>      >
>>>      >                    @Bean
>>>      >                    public FooRepsitory fooRepository() {
>>>      >                        return new
>>>     HibernateFooRepository(__sessionFactory());
>>>      >                    }
>>>      >
>>>      >                    @Bean
>>>      >                    public SessionFactory sessionFactory() {
>>>      >                        return new AnnotationSessionFactoryBuilde__r()
>>>      >                            .setDataSource(dataSource())
>>>      >                            .setSchemaUpdate(true)
>>>      >                            .setAnnotatedClasses(Foo.__class)
>>>      >                            .buildSessionFactory();
>>>      >                    }
>>>      >
>>>      >                    @Bean
>>>      >                    public DataSource dataSource() {
>>>      >                        return new EmbeddedDatabaseBuilder()
>>>      >                            .setType(EmbeddedDatabaseType.__HSQL)
>>>      >                            .build();
>>>      >                    }
>>>      >
>>>      >               }
>>>      >
>>>      >
>>>      >               Such a @Configuration class may then used to
>>>     bootstrap the
>>>      >               application.
>>>      >                 If we're dealing with a simple standalone Java
>>>      >               application, doing so
>>>      >               within a main method will suffice:
>>>      >
>>>      >               package com.myco.app;
>>>      >
>>>      >               import
>>>      >
>>>
>>>   org.springframework.context.__annotation.__AnnotationConfigApplicationCon__text;
>>>      >
>>>      >               import com.myco.domain.Foo;
>>>      >               import com.myco.app.service.__FooService;
>>>      >               import com.myco.app.config.__MyApplicationConfig;
>>>      >
>>>      >               public class Bootstrap {
>>>      >                    public static void main(String... args) {
>>>      >                        AnnotationConfigApplicationCon__text ctx = new
>>>      >               AnnotationConfigApplicationCon__text();
>>>      >                        ctx.register(__MyApplicationConfig.class);
>>>      >                        ctx.refresh();
>>>      >
>>>      >                        FooService fooService =
>>>       ctx.getBean(FooService.class);
>>>      >                        Foo foo1234 = fooService.findById(1234);
>>>      >                        System.out.println(foo1234);
>>>      >                    }
>>>      >               }
>>>      >
>>>      >
>>>      >               Now let's get to the business of method literals.
>>>   Notice
>>>      >               again the
>>>      >               Hibernate SessionFactory @Bean definition:
>>>      >
>>>      >                    @Bean
>>>      >                    public SessionFactory sessionFactory() {
>>>      >                        // ...
>>>      >                    }
>>>      >
>>>      >
>>>      >               The SessionFactory is being created by Spring here,
>>>     and will
>>>      >               be managed by
>>>      >               the Spring container for the lifetime of the
>>>     ApplicationContext
>>>      >               bootstrapped in our main method.  Note however that its
>>>      >               configuration is
>>>      >               not yet complete - it is important to call a
>>>      >               SessionFactory's close()
>>>      >               method on application shutdown in order to manage
>>>     resources
>>>      >               properly, and
>>>      >               Spring provides a mechanism to allow users to specify
>>>     this
>>>      >               with the
>>>      >  'destroyMethod' attribute of the @Bean annotation:
>>>      >
>>>      >                    @Bean(destroyMethod="close")
>>>      >                    public SessionFactory sessionFactory() {
>>>      >                        // ...
>>>      >                    }
>>>      >
>>>      >               You can see the problem - 'close' must be specified as a
>>>      >               string due to
>>>      >               lack of method literal support in the language.  Far
>>> more
>>>      >               desirable would
>>>      >               be:
>>>      >
>>>      >                    @Bean(destroyMethod=__SessionFactory#close)
>>>      >                    public SessionFactory sessionFactory() {
>>>      >                        // ...
>>>      >                    }
>>>      >
>>>      >               Whether the user is referring to an instance method or
>>>      >               static method is,
>>>      >               from the framework's point of view, immaterial.  We
>>>     simply
>>>      >               wish to provide
>>>      >               the user with an IDE-friendly mechanism to execute a
>>>     method
>>>      >               during the
>>>      >               destruction phase of the bean lifecycle.  We can do this
>>>      >               already, but it
>>>      >               requires stringification of method names.
>>>      >
>>>      >               This is certainly not our only use case, but in the
>>>     interest
>>>      >               of brevity
>>>      >               I'll leave it here, noting that our use cases are not
>>>      >               limited to method
>>>      >               literals within annotations; such syntax would be useful
>>>      >               within many
>>>      >               contexts.  For a non-Spring example, consider the case
>>> of
>>>      >               JPA 2's Criteria
>>>      >               API, which is crippled by the lack of field literals
>>>     in the
>>>      >               language.  Its
>>>      >               use is so cumbersome that the QueryDSL project has
>>> become
>>>      >               quite popular in
>>>      >               conjunction with JPA, as they take an APT-based code gen
>>>      >               approach that
>>>      >               effectively approximates the functionality of field
>>>     literals
>>>      >               [1].  Again, I
>>>      >               find the utility of field and method literals
>>>     self-evident,
>>>      >               even obvious.
>>>      >                 It is certainly not a Spring-specific itch we wish to
>>>      >               scratch here, but
>>>      >               rather to champion a generally useful addition to the
>>>     language.
>>>      >
>>>      >               Are there fundamental objections to such support?  Does
>>>      >               prior art in
>>>      >               Project Lambda already encompass these use cases?
>>>       We'd be
>>>      >               interested in
>>>      >               hearing what next steps are necessary to help make this
>>> a
>>>      >               reality in JDK 8
>>>      >               and how we can help.
>>>      >
>>>      >               Thanks,
>>>      >
>>>      >               - Chris
>>>      >
>>>      >               [1]:
>>>      >  http://source.mysema.com/__forum/mvnforum/viewthread___thread,49
>>>      >  <http://source.mysema.com/forum/mvnforum/viewthread_thread,49>
>>>      >
>>>      >
>>>      >
>>>      >
>>>      >
>>>      >
>>>      >
>>>      >
>>>      >  --
>>>      >  @matthewadams12
>>>      >  mailto:matthew at matthewadams.me<mailto:matthew at matthewadams.me>
>>>     <mailto:matthew at matthewadams.me<mailto:matthew at matthewadams.me>>
>>>      >  skype:matthewadams12
>>>      >  yahoo:matthewadams
>>>      >  aol:matthewadams12
>>>      >  google-talk:matthewadams12 at gmail.com
>>>     <mailto:google-talk%3Amatthewadams12 at gmail.com>
>>>      >  <mailto:google-talk%3Amatthewadams12 at gmail.com
>>>     <mailto:google-talk%253Amatthewadams12 at gmail.com>>
>>>      >  msn:matthew at matthewadams.me
>>>     <mailto:msn%3Amatthew at matthewadams.me>
>>>     <mailto:msn%3Amatthew at matthewadams.me
>>>     <mailto:msn%253Amatthew at matthewadams.me>>
>>>      >  http://matthewadams.me
>>>      >  http://www.linkedin.com/in/matthewadams
>>>      >
>>>
>>>
>>
>
>
>


More information about the lambda-dev mailing list