var, static factory method and value type constructor

forax at univ-mlv.fr forax at univ-mlv.fr
Tue Oct 9 14:17:27 UTC 2018


----- Mail original -----
> De: "Brian Goetz" <brian.goetz at oracle.com>
> À: "Remi Forax" <forax at univ-mlv.fr>, "valhalla-spec-experts" <valhalla-spec-experts at openjdk.java.net>
> Envoyé: Lundi 8 Octobre 2018 16:43:58
> Objet: Re: var, static factory method and value type constructor

> The fact that factory methods are pure convention, rather than something
> understood by the language and tool chain (e.g., should be segregated
> from other static methods by Javadoc), has caused challenges for a
> number of features, and so some more formal notion of "factory method"
> is a reasonable thing to put on the table.  This comes up, for example,
> in records -- one of the unfortunate compromises (without a linguistic
> notion of factories) is users get forced to choose between using records
> and encapsulating the constructor.
> 
> The syntax you propose has the problem (though some might say it is a
> strength) that it gives up one of the best things about factory methods:
> naming.  Being able to have separate names is useful both to class
> authors (makes it more clear what the member does) and clients (code is
> more self-descriptive.)

as usual with names, sometimes you want names, sometimes you do not want them, we have pojo class vs anonymous class, we have method references vs lambdas, we have a plain old type for local variables vs var, we have a plain old static call vs a static import, in all these examples it's about giving a name or not giving a name to something, likewise, for factory method, sometimes you want a name, sometimes you don't want a name.

With a static method, there is a name, with a constructor, there is no name. Here, i want to focus on the no name part, we have in the JDK, factory methods that have a not very meaningful name, Path.of/List.of, MethodType.methodType, etc. those "constructors" are static methods for an implementation reason and not because they have a meaningful name (they don't). For those cases, i want to re-use "new" as the factory method name (because the name is not meaningful) and i want users to be able to use 'new' so it makes Java easier to learn by removing things you do not have to learn yet to be able to use JDK classes.

> 
> All that said, does this help your students in this case beyond having a
> more obvious and uniform place to put the type witnesses -- new Foo<T>()
> rather than Foo.<T>of() -- or is that the whole story ?

Having a simple way to use the basic classes of the JDK will help my students when they start to learn the langage.

The other side of this discussion is the support of constructors inside a value type, currently javac transforms the constructors as static factories with a weird name. Syntactic sugar like this has a cost for our users because at runtime, you see the compiler scaffolding, when debugging, when using reflection, in the stacktrace, etc. Interpreting the scaffolding is easy if there is a way to express the construction in Java, having a way for user to create a factory method that acts as a constructor will help. 

Rémi

> 
> On 10/6/2018 5:55 AM, Remi Forax wrote:
>> I've observed an interesting side effect of the introduction of var that
>> troubles my students,
>> the introduction of var make the generics method call with type arguments needed
>> to be mentioned more frequent.
>>
>> writing
>>    List<String> list = List.of();
>>    foo(list);   // foo takes a List of String
>> works out of the box but
>>    var list = List.of();
>>    foo(list);
>> will not compile because list is inferred as List<Object>
>>
>> Explicitly specifying the type arguments
>>    var list = List.<String>of();
>>    foo(list);
>> works but this syntax is far from obvious for my students.
>>
>> This lead me to think again about introducing a syntax for supporting static
>> factory method (yes, i know, it seems remote, but it's connected).
>> My students has no issue with specifying the type argument when calling a
>> constructor
>>    var list = new ArrayList<String>();
>> so
>>    why not resurrect the proposal to have a syntax to be able to declare static
>>    factory method at language level and being able to call it with new ?
>>
>> I propose to re-use 'new' when defining a static factory method
>>    interface Fun {
>>      static Fun new() {
>>        return ...
>>      }
>>    }
>>
>> and teach the compiler that new Fun() should be translated to invokestatic
>> Fun.new() in this case.
>>
>> It is obvioulsly related to value types and the way the compiler currently
>> desugars constructor of value type. The desugaring of the constructor call is
>> exactly the same as this proposal,
>> what we are adding here is the fact that a developer can ask for such
>> translation by adding a static factory instead of being only a magic
>> translation from the compiler.
>>
>> Rémi


More information about the valhalla-spec-experts mailing list