Banning constructors in value classes (JDK-8198749) (original) (raw)

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 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 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 .) 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 methods in value classes - with tentative semantics being discussed for invokespecial to throw an exception if it encounters an 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 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