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