JEP 401 includes special JVM factory methods, spelled <new> (or, alternatively, 
<init> with a non-void return), which are needed as a standardized way to 
encode the Java language's primitive class constructors.

We have a lot of flexibility in how much we restrict use of these methods. Too 
many restrictions seem arbitrary and incoherent from the JVM's point of view; 
but too few restrictions risk untested corner cases, unfortunate compatibility 
obligations, and difficulties mapping back to the Java language model.

Expanding on that last one: for tools that operate with a Java language model, 
there are essentially three strategies for dealing with factory methods outside 
of the core primitive class construction use case:

1) Have the JVM reject them
2) Ignore them
3) Expand the model to include them

Taking javac as an example, here's what that looks like:

1) If factory methods outside of primitive classes are illegal, javac can treat 
classes with such methods as malformed and report an error.

2) Or if javac sees a factory method in a non-primitive class, it can just 
leave it out when it maps the class file to a language-level class. (There's 
precedent for this in, e.g., the treatment of fields with the same name and 
different descriptors.)

3) Or we can allow javac to view factory methods in any class as constructors. 
A few complications:

    - Constructors of non-final classes have both 'new Foo()' and 'super()' 
entry points; factories only support the first. So we either need to validate 
that a matching pair of <new> and <init> exist, or expand the language to model 
factories independently from constructors.

    - The language expects instance creation expressions to create fresh 
instances. We need to either validate this behavior (does the factory look like 
"new/dup/<init>"?) or relax the language semantics (perhaps this is in the grey 
area of mixed binaries?)

    - Factories can appear in abstract classes and interfaces. Again, are we 
willing to change the language model to support these use cases? Perhaps to 
even allow their declaration?

    - If a factory method has a mismatched return type (declared in Foo, but 
returns a Bar), are we willing to support a type system where the type of a 
factory invocation is not the type of the class to which the factory belongs?

There are probably limits to what we're willing to do with (3), which pushes at 
least some cases into the (1) or (2) buckets.

So, my question: what should we expect from (3), now and in the foreseeable 
future? And for the cases that fall outside of it, should we fall back to (1), 
(2), or a mixture of both?

Reply via email to