Field and Method Literals

Matthew Adams matthew at matthewadams.me
Tue Nov 22 10:18:06 PST 2011


Ok, I didn't mean to start a whole crapstorm by asking.
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
>>     >
>>
>>
>



-- 
@matthewadams12
mailto:matthew at matthewadams.me
skype:matthewadams12
yahoo:matthewadams
aol:matthewadams12
google-talk:matthewadams12 at gmail.com
msn:matthew at matthewadams.me
http://matthewadams.me
http://www.linkedin.com/in/matthewadams


More information about the lambda-dev mailing list