Loosen Constructor super()/this() call restrictions (original) (raw)

Mike Duigou Mike.Duigou at Sun.COM
Sun Mar 22 15:55:57 PDT 2009


 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.


More information about the coin-dev mailing list