Field and Method Literals
Brian Goetz
brian.goetz at oracle.com
Mon Nov 21 09:39:25 PST 2011
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 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> wrote:
>
>> On Sun, Apr 17, 2011 at 8:14 PM, Collin Fagan<collin.fagan at 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.AnnotationSessionFactoryBuilder;
>>
>> 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 AnnotationSessionFactoryBuilder()
>> .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.AnnotationConfigApplicationContext;
>>
>> 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) {
>> AnnotationConfigApplicationContext ctx = new
>> AnnotationConfigApplicationContext();
>> 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
>>
>>
>>
>
>
More information about the lambda-dev
mailing list