core/play/src/main/java/play/libs/reflect/MemberUtils.java
private static float getTotalTransformationCost(
      final Class<?>[] srcArgs, final Executable executable) {
    final Class<?>[] destArgs = executable.getParameterTypes();
    final boolean isVarArgs = executable.isVarArgs();

    // "source" and "destination" are the actual and declared args respectively.
    float totalCost = 0.0f;
    final long normalArgsLen = isVarArgs ? destArgs.length - 1 : destArgs.length;
    if (srcArgs.length < normalArgsLen) {
      return Float.MAX_VALUE;
    }
    for (int i = 0; i < normalArgsLen; i++) {
      totalCost += getObjectTransformationCost(srcArgs[i], destArgs[i]);
    }
    if (isVarArgs) {
      // When isVarArgs is true, srcArgs and dstArgs may differ in length.
      // There are two special cases to consider:
      final boolean noVarArgsPassed = srcArgs.length < destArgs.length;
      final boolean explicitArrayForVarags =
          srcArgs.length == destArgs.length && srcArgs[srcArgs.length - 1].isArray();

      final float varArgsCost = 0.001f;
      final Class<?> destClass = destArgs[destArgs.length - 1].getComponentType();
      if (noVarArgsPassed) {
        // When no varargs passed, the best match is the most generic matching type, not the most
        // specific.
        totalCost += getObjectTransformationCost(destClass, Object.class) + varArgsCost;
      } else if (explicitArrayForVarags) {
        final Class<?> sourceClass = srcArgs[srcArgs.length - 1].getComponentType();
        totalCost += getObjectTransformationCost(sourceClass, destClass) + varArgsCost;
      } else {
        // This is typical varargs case.
        for (int i = destArgs.length - 1; i < srcArgs.length; i++) {
          final Class<?> srcClass = srcArgs[i];
          totalCost += getObjectTransformationCost(srcClass, destClass) + varArgsCost;
        }
      }
    }
    return totalCost;
  }
private static float getTotalTransformationCost(
      final Class<?>[] srcArgs, final Executable executable) {
    final Class<?>[] destArgs = executable.getParameterTypes();
    final boolean isVarArgs = executable.isVarArgs();

    // "source" and "destination" are the actual and declared args respectively.
    float totalCost = 0.0f;
    final long normalArgsLen = isVarArgs ? destArgs.length - 1 : destArgs.length;
    if (srcArgs.length < normalArgsLen) {
      return Float.MAX_VALUE;
    }
    for (int i = 0; i < normalArgsLen; i++) {
      totalCost += getObjectTransformationCost(srcArgs[i], destArgs[i]);
    }
    if (isVarArgs) {
      // When isVarArgs is true, srcArgs and dstArgs may differ in length.
      // There are two special cases to consider:
      final boolean noVarArgsPassed = srcArgs.length < destArgs.length;
      final boolean explicitArrayForVarags =
          srcArgs.length == destArgs.length && srcArgs[srcArgs.length - 1].isArray();

      final float varArgsCost = 0.001f;
      final Class<?> destClass = destArgs[destArgs.length - 1].getComponentType();
      if (noVarArgsPassed) {
        // When no varargs passed, the best match is the most generic matching type, not the most
        // specific.
        totalCost += getObjectTransformationCost(destClass, Object.class) + varArgsCost;
      } else if (explicitArrayForVarags) {
        final Class<?> sourceClass = srcArgs[srcArgs.length - 1].getComponentType();
        totalCost += getObjectTransformationCost(sourceClass, destClass) + varArgsCost;
      } else {
        // This is typical varargs case.
        for (int i = destArgs.length - 1; i < srcArgs.length; i++) {
          final Class<?> srcClass = srcArgs[i];
          totalCost += getObjectTransformationCost(srcClass, destClass) + varArgsCost;
        }
      }
    }
    return totalCost;
  }
Returns the sum of the object transformation cost for each class in the source argument list.

@param srcArgs The source arguments
@param executable The executable to calculate transformation costs for
@return The total transformation cost