JSR-282 SI 14: Provide overloaded forms of all object creating methods to take a destination object instead ----------------------------------------------------------------------------------------------------------- Last Updated: 24/6/2006 ----------------------- Summary ------- Define overloaded forms of methods that normally create and return new objects so they instead fill-in and return a passed in destination object. Specification References ----------------------- Problem being addressed ------------------------------ Many of the API methods in javax.realtime cause the creation of objects. For example AbsoluteTime.add(long millis, int nanos) creates a new AbsoluteTime object with a value equal to the current time object plus the given millis and nanos values. Because memory management is a critical part of the RTSJ, allocation needs to be controllable by the application. Consequently, methods that cause the creation of objects, generally have a second overloaded form that takes a destination object instead. For example, AbsoluteTime(long millis, int nanos, AbsoluteTime dest) sets the value of dest to be the value of the current time object plus millis and nanos. In some API's however, the overloaded form taking the destination object is missing. Proposed Solution Summary ------------------------------------- For each object creating method that is missing the overloaded form that takes a destination object, the overloaded form will be added. Semantics of Proposed Solution ---------------------------------------- The semantics of the overloaded forms are that if the destination object is not null then it is used to hold the result of the method and returned by the method. If the destination object is null then a new object will created. Hence it should always be the case that given a pair of methods: Obj foo(int args); Obj foo(int args, Obj dest); that in terms of semantics, the former can be implemented by invoking the latter with a null destination object, ie: Obj foo(int args) { return foo(args, null); } NOTE: there is a risk in changing any existing implementation to do the above -see issues below. NOTE 2: while most existing API's follow the above semantics, the Clock.getTime(dest) method ignores a null dest and simply returns null In some cases the return type of the method may be a supertype of the actual object that would be created, and the actual type is not know a-priori. In that case the destination object may be the wrong kind - such as passing a PeriodicParameters object for ReleaseParameters when it needs to be SporadicParameters. In this situation we have two options: a) ignore the destination object and create the correct type (as if dest was null) b) throw ClassCastException The methods to be added are: AbsoluteTime: Date getDate(Date dest); Clock: RelativeTime getEpochOffset(RelativeTime dest); RelativeTime getResolution(RelativeTime dest); GarbageCollector: RelativeTime getPreemptionLatency(RelativeTime dest); Additions that have destination type issues: AsyncEvent: (and inherited by Timer) ReleaseParameters createReleaseParameters(ReleaseParameters dest) Compatability Issues: --------------------- There are five situations where adding these methods to the existing classes would result in compile-time errors in application code - all of which involve subclassing: a) the subclass has a static method that has the same signature as the added method b) the subclass has an instance method that has the same signature as the added method but differs in return type c) the subclass has an instance method that has the same signature and return type as the added method but is not public d) the subclass has an instance method that has the same signature and return type as the added method but throws checked exceptions not thrown by the added method e) the subclass defines a different overloaded form of the method, but with argument types that are supertypes, or subtypes, of the argument types for the added method. This in itself is not an error but some calls to the existing method may now be considered ambiguous. Given the nature of the classes and methods we are dealing with it is very unlikely that any subclass exists that performs one of the above actions. The most likely scenario is that the subclass adds the method that we are now defining, in which case the existing subclass method will simply override the newly defined one. But these compatability issues must be documented. NOTE: The possibility that a subclass already provides the overloaded form that we are adding means that the implementation of the existing methods can not be rewritten to use the new form as described in the semantics section. If a subclass already defines the destination-object form as follows: Obj foo(int args, Obj dest) { if (dest == null) return foo(args); else { ... return dest; } } then changing the existing "Obj foo(int x)" method to invoke "foo(x, null)" would result in an infinite loop.