Choosing among overloaded methods

If there is no method with the required name and number of parameters, Saxon reports a compile-time error.

If there is only one method with the required name and number of parameters, then Saxon chooses it, and goes on to the next stage, which allocates converters for the supplied arguments.

If there are several methods in the class that match the localname, and that have the correct number of arguments, then the system attempts to find the one that is the best fit to the types of the supplied arguments: for example if the call is f(1,2) then a method with two int arguments will be preferred to one with two float arguments. This decision is typically made during static type analysis. The rules for deciding between methods are quite complex. Essentially, for each candidate method, Saxon calculates the "distance" between the types of the supplied arguments and the Java class of the corresponding method in the method's signature, using a set of tables (see below). For example, the distance between the XPath data type xs:integer and the Java class long is very small, while the distance between an XPath xs:integer and a Java Object is much larger. If there is one candidate method where the distances of all arguments are less-than-or-equal-to the distances computed for other candidate methods, and the distance of at least one argument is smaller, then that method is chosen.

If there are several methods with the same name and the correct number of arguments, but none is preferable to the others under these rules, an error is reported: the message indicates that there is more than one method that matches the function call.

This binding is carried out statically, using the static types of the supplied arguments, not the dynamic types obtained when the arguments are evaluated. If there is insufficient static type information to distinguish the candidate methods, an error is reported. You can supply additional type information using the treat as expression, or by casting. Often it is enough simply to declare the types of the variables used as arguments to the function call.

The distances are calculated using the following rules (in order).

  • If the required type is Object, the distance is 100.

  • If the required type is one of the following Saxon-specific classes (or is a superclass of that class), then the distance is as given:

    Note that Saxon does not recognize the classes defined in the s9api package for use with extension functions (for example, XdmNode and XdmAtomicValue).

  • If the static type of the supplied argument allows more than one item, the distance is the first one of the following that applies:

    • If the method expects java.lang.Collection or a class that implements Collection: 30

    • If the method expects an array: 31

    • In all other cases: 80

    Note that the item type of the supplied value plays no role in choosing the method to call, even though it could potentially be used to disambiguate overloaded methods when arrays or parameterized collection types are used.

  • Otherwise (the static type allows only one item):

    • If the static type of the supplied value matches node(): 80

    • If the static type of the supplied value is a wrapped Java object, then 10 if the class of the object matches the required Java class, else -1 (meaning this method is not a candidate)

    • Otherwise, the value given by the table of atomic types below.

For each of the atomic types listed below, the distance between the supplied type and the first corresponding required type (the Saxon-specific class in italics) is 50. Distances then increase (by 1 or 2) as you go along the ordered list of other possible required types. If there is no entry for the combination of supplied type and required type, the method is removed from consideration. For unboxed types (int, float, etc) the distance is always one less than the corresponding boxed type (java.lang.Integer, java.lang.Float).

Supplied type

Required type

xs:string

StringValue, String, CharSequence

xs:boolean

BooleanValue, Boolean

xs:float

FloatValue, Float, Double

xs:double

DoubleValue, Double

xs:decimal

DecimalValue, BigDecimal, Double, Float

xs:integer

IntegerValue, BigInteger, BigDecimal, Long, Integer, Short, Byte, Double, Float

xs:date, xs:gDay, xs:gMonthDay, xs:gMonth, xs:gYearMonth, xs: gYear

DateValue, Date

xs:dateTime

DateTimeValue, Date

xs:time

TimeValue

xs:duration, xs:yearMonthDuration, xs:dayTimeDuration

DurationValue

xs:hexBinary

HexBinaryValue

xs:base64Binary

Base64BinaryValue

xs:anyURI

AnyURIValue, java.net.URI, java.net.URL, String, CharSequence

xs:QName

QNameValue, javax.xml.namespace.QName

Saxon tries to select the appropriate method based on the static type of the arguments to the function call. If there are several candidate methods, and there is insufficient information available to decide which is most appropriate, an error is reported. The remedy is to cast the arguments to a more specific type.

A required type of one of the Java primitive types such as int or bool is treated as equivalent to the corresponding boxed type (Integer or Boolean), except that with the boxed types, an empty sequence can be supplied in the function call and is translated to a Java null value as the actual argument.

The fact that a particular method is chosen as the target does not give a guarantee that conversion of the arguments will succeed at run-time. This is particularly true with methods that expect a node in an external object model such as DOM or XOM.