Banning constructors in value classes (JDK-8198749)

John Rose john.r.rose at oracle.com
Tue Feb 27 16:31:00 UTC 2018


This is a timely question.  There are two parts to it:  1. whether <init> belongs in
value type classfiles? 2. whether constructors belong in value type sourcefiles?

The answers are no and yes, and that's not a contradiction but a requirement
of translation strategy.  Although <init> makes sense only for object classes,
constructors are part of the "codes like a class, works like an int" story for
values.

I discussed constructor semantics in detail here:
  http://mail.openjdk.java.net/pipermail/valhalla-spec-experts/2018-February/000581.html <http://mail.openjdk.java.net/pipermail/valhalla-spec-experts/2018-February/000581.html>

I recommend prototyping those semantics to see if they really hold up.
Semantic compatibility of constructors is a more fruitful approach to
value classes than a new separate sub-language for factories.

(I am not saying we don't need some sort of "with" statement, but
*first* we need to reinterpret constructors, saving the "codes like
a class" thesis.  *Then* I think the story for "with" statements will
be more clear, perhaps as a variant on constructor bodies or else as
a sugar for calling constructors by named parameters.)

In short, all the AST-level rules for constructors remain, including
DA/DU tracking of blank finals.  The semantics of an initializing
write to a field 'this.x = y' are 'this = __WithField(this.x, y)'.  Yes,
'this' in a value type is assignable, exactly in places where a
final variable can be written.  In both cases, immutable state
is being written, and there is restricted access to 'this'.  The
two factors balance together to deal with the paradox of
writing data to an immutable—whether it is an object or it
is a value.

AFAIK there is no reason to remove *any* source-level feature
of the constructor language, given a proper translation strategy for
constructors.  So please try to keep features such as instance
initializers and (even though pretty useless) field initializers.
(Those features are defined at source level as inclusions in
the logical source code of the constructor, before lowering
to <init>.)  We may salvage such features for record types,
so we don't want to introduce an unneeded asymmetry
between objects and values.

— John

On Feb 27, 2018, at 5:29 AM, Srikanth <srikanth.adayapalam at oracle.com> wrote:
> 
> 
> There has been some discussion about banning <init> methods in value classes - with tentative semantics being discussed for invokespecial to throw an exception if it encounters an <init> method in a value class.
> 
> (See http://mail.openjdk.java.net/pipermail/valhalla-dev/2018-January/003709.html  and
> http://mail.openjdk.java.net/pipermail/valhalla-dev/2018-January/003712.html <http://mail.openjdk.java.net/pipermail/valhalla-dev/2018-January/003712.html:>
> and https://bugs.openjdk.java.net/browse/JDK-8198749)
> 
> 
> Already, any attempt to create a value class instance via the new operator is forbidden by javac and neither __MakeDefault not withfield operation make use of the constructors. So any constructors are dead code and it makes sense at the outset to get rid of them.
> 
> I prototyped this in javac and this is what this means:
> 
>     - All instance fields of value classes must be blank final variables. No initialization can be allowed.
> (With <init> methods going away, there is no place to stick these initializers)
>     - For the same reason, there cannot be instance initializer blocks in a value class.
>      - Value classes may not declare any constructors
>      - The compiler may generate a default constructor to simplify its life, but such a generated constructor will not make it to the class file.
>     - For value classes, the compiler will relax the requirement that all blank final instance variables must be initialized before any constructor finishes - there are no constructors, so this cannot/need not be/will not be enforced.
> 
> I am still testing this prototype, but at the moment I am not aware of any problems, but a question: I imagine it should be possible to invoke j.l.O methods on a value instance and have them be routed to j.l.O implementation or to the override - will this work without constructor chaining - (No such chaining is happening anyways already)
> 
> Frederic/John, is this something you want to see pushed to the branch ? (assuming further testing does not uncover any problems) Or should this wait ?
> 
> Thanks!
> Srikanth



More information about the valhalla-dev mailing list