Loosen Constructor super()/this() call restrictions
Mike Duigou
Mike.Duigou at Sun.COM
Sun Mar 22 21:39:03 PDT 2009
On Mar 22, 2009, at 6:07 PM, Jeremy Manson wrote:
> Also, you probably need to state that super will now be inserted as
> the first thing that happens in a constructor only when static
> analysis determines that there are no calls to super() or this() in
> the code.
>
> One of the benefits of super() being the first thing called in a
> constructor was that a subclass could never see a partially
> initialized version of its super-class stuff. With that in mind, what
> are the new semantics like?
My intention was not to not change initialization sematics. Since no
access is allowed to any instance methods or fields before the super()
the object need not be constructed until the super() call is actually
made.
> For example, now that this() and super() can come in the middle of a
> constructor, are the semantics implicitly changed so that you can
> catch exceptions thrown by this() and super()? Does that mean that
> objects can now be seen as partially initialized in sub-constructors?
>
> In the same vein, is there any desire to prevent code from accessing
> fields / methods of superclasses before super() is invoked?
>
I don't wish to change the object initialization semantics at all. No
access to instance fields or methods is allowed before an explicit
super()/this() call and if there is no explicit super() then an
implicit super() is added before the first time "this" is needed to
access either field or method. Sorry if that wasn't clear. Changing
the initialization semantics to make partially constructed objects
visible would make an unholy mess that I can't imagine would ever be
worthwhile.
> Jeremy
>
> On Sun, Mar 22, 2009 at 5:49 PM, Jeremy Manson <jeremy.manson at gmail.com
> > wrote:
>> It seems to me that you might need more semantics. For example, the
>> specification should probably work with the definite assignment rules
>> to make sure that the calls to super / this, if present, both
>> definitely happen and only happen exactly once per constructor. Here
>> are a couple of constructors for class Foo that should probably
>> result
>> in compilation errors:
>>
>> Foo() {
>> if (something) {
>> super(blah)
>> }
>> }
>> Foo() {
>> super(blah);
>> super(blah);
>> }
>>
>> Also, it seems to me that you would want to be careful about access
>> to
>> fields of the parent object before the invocation of super().
>>
>> Jeremy
>>
>> On Sun, Mar 22, 2009 at 3:55 PM, Mike Duigou <Mike.Duigou at sun.com>
>> wrote:
>>> AUTHOR(S): Mike Duigou
>>>
>>> OVERVIEW
>>>
>>> FEATURE SUMMARY: Currently, if present, a call to another
>>> constructer via super() or this() must be the first statement of a
>>> constructor. This proposal would loosen the restrictions on calls to
>>> super() and this () to allow local variable declaration and several
>>> types of statements to appear before the call to super() or this().
>>>
>>> MAJOR ADVANTAGE: This proposal is most useful when the
>>> constructor parameters must be mutated before calling the other
>>> super() or this() constructor.
>>>
>>> MAJOR BENEFIT: This proposal may allow for simpler, easier to
>>> understand constructions in the calling of super() and this()
>>> constructors. It also eliminates the need for some static factory
>>> methods which are currently used to work around this problem. The
>>> resulting code is more uniform in the use of constructors to create
>>> objects.
>>>
>>> MAJOR DISADVANTAGE: This is a change to the Java language
>>> grammar
>>> and will require changes to compilers, static analysis tools and any
>>> other uses that parse Java source code.
>>>
>>> ALTERNATIVES: The common alternatives when the input parameters
>>> cannot be easily mutated into the required parameters for calling
>>> another constructor are to provide a static factory method that does
>>> the work instead of a constructor. Private varargs constructors that
>>> understand a specific order of parameters passed are also used.
>>>
>>> EXAMPLES
>>>
>>> Show us the code!
>>>
>>> SIMPLE EXAMPLE:
>>>
>>> /**
>>> * presents a measurement in fractional inches.
>>> */
>>> public class Inches {
>>> private final int numerator;
>>>
>>> private final int denominator;
>>>
>>> public Inches( int numerator, int denominator ) {
>>> this.numerator = numerator;
>>> this.denominator = denominator;
>>> }
>>>
>>> public Inches( int whole, int numerator, int
>>> denominator ) {
>>> // simple this() call
>>> this( whole * denominator + numerator,
>>> denominator );
>>> }
>>>
>>> /**
>>> * A private constructor for the unpleasant technique of
>>> using var args to pass
>>> * constructor parameters.
>>> */
>>> private Inches( int ... params ) {
>>> this(params[0], params[1]);
>>> }
>>>
>>> /**
>>> * Makes use of a static method to transform decimal
>>> into
>>> numerator and denominator
>>> * which are then passed to the private varargs
>>> constructor.
>>> */
>>> public Inches( float decimal ) {
>>> this(convert(decimal));
>>> }
>>>
>>> /**
>>> * produces a length 2 int array with the numerator at
>>> index 0 and
>>> the
>>> * denominator at index 1
>>> */
>>> private static int[] convert(float decimal) {
>>> int[] result = new int[2]; // [0] numerator, [1]
>>> denominator
>>>
>>> // ... conversion happens here ...
>>>
>>> return result;
>>> }
>>>
>>> /**
>>> * Static factory method which does the conversion and
>>> returns
>>> * a new Inch object
>>> */
>>> public static Inches toInches(double) {
>>> int dec_numerator;
>>> int dec_denominator;
>>>
>>> // ... conversion happens here ...
>>>
>>> return new Inches( dec_numerator, dec_denominator );
>>> }
>>>
>>> /**
>>> * Converts a decimal fraction measurement in inches to
>>> it's closest fractional representation.
>>> * Note : accuracy is limited to 1/1024th.
>>> */
>>> public Inches( double decimal ) {
>>> int dec_numerator; // not allowed by Java 6
>>> grammar
>>> int dec_denominator;
>>>
>>> if( Math.abs(decimal) < (1.0 / 1024) ) {
>>> dec_numerator = 0;
>>> dec_denominator = 1;
>>> } else {
>>> // ... conversion happens here ...
>>> }
>>>
>>> this( dec_numerator, dec_denominator );
>>> }
>>>
>>> The Inches(double decimal) constructor demonstrates the
>>> new
>>> grammar by declaring local variables and performing calculations
>>> upon
>>> the input parameter before calling another constructor via this().
>>> This example is important because the conversion from a decimal
>>> fraction to a numerator and denominator produces two results from
>>> one
>>> input.
>>>
>>> DETAILS
>>>
>>> SPECIFICATION: The grammar is extended to allow declaration of
>>> local variables and statements involving only local variables,
>>> parameters, static fields and static methods to occur before the
>>> super() or this() constructor is called.
>>>
>>> COMPILATION: Unknown impact.
>>>
>>> TESTING: No special testing requirements are required for this
>>> extension. Simple unit tests should be able to exercise all of
>>> the required behaviour.
>>>
>>> LIBRARY SUPPORT: None.
>>>
>>> REFLECTIVE APIS: Calling constructors via reflection as an
>>> alternative to explicit calls to this() or super() constructors is
>>> not
>>> currently supported and this change does not impact that.
>>>
>>> OTHER CHANGES: No changes are likely needed to JNI, Javadoc or
>>> JPDA.
>>>
>>> MIGRATION: Most source changes to use this feature would be
>>> manually performed as they likely entail the introduction of new
>>> local
>>> variables to hold intermediate results before super() or this() is
>>> called. New constructors could be provided to take the place of
>>> static
>>> factory methods and the methods deprecated and replaced with one
>>> statement bodies consisting of "return new Foo()" with matching
>>> params
>>> to their own.
>>>
>>> COMPATIBILITY
>>>
>>> BREAKING CHANGES: I believe this change is 100% backwards
>>> compatible for source code as it does not restrict or change the
>>> meaning of any existing statements.
>>>
>>> EXISTING PROGRAMS: As all of the changes are captured within the
>>> constructor method it is unlikely existing programs would be
>>> impacted by this change.
>>>
>>> REFERENCES
>>>
>>> EXISTING BUGS: None known.
>>>
>>> URL FOR PROTOTYPE (optional): None available.
>>>
>>>
>>>
>>
--
Mike Duigou
Senior Staff Engineer
APS CSG CTO AD
Sun Microsystems Inc.
More information about the coin-dev
mailing list