Loosen Constructor super()/this() call restrictions

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