Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4856541

add varargs support

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Fixed
    • Icon: P3 P3
    • 5.0
    • 1.4.2
    • tools
    • tiger
    • x86
    • windows_2000

      Adding varargs to Java

      Abstract

      We propose to add variable argument list methods to Java. Existing methods (such as java.text.MessageFormat.format) could be retrofitted to accept variable argument lists without affecting existing clients, while enabling new clients to use an improved invocation syntax. The overload resolution algorithm is modified to support variable argument lists, boxing, and unboxing while retaining backward compatibility both at compile-time and runtime. The implementation resides entirely in the compiler; no support in the VM is necessary.

      Motivation

      Java has two different kinds of interfaces for composing text output. The first kind consists of chained or sequential method calls such as those from java.io.PrintStream or composition using java.lang.StringBuffer (or the moral equivalent using String concatenation). These methods are convenient and statically typesafe but these techniques do not internationalize well because the order of "snippets" in a message are fixed by the order of calls in the source. The second kind consists of "formatting" classes such as java.text.MessageFormat and related classes that support internationalization. These interfaces are awkward to use and are not statically typesafe, but internationalization is easily supported because the format argument that specifies the order and content of the assembly of the resulting message can be replaced at runtime with one appropriate to the user's native tongue. Think "resource files".

      The ideal would be formatting classes that are easy to use, internationalizable, and statically typesafe. These three goals cannot be achieved without nontrivial innovation in the language. Instead we propose a simple language extension that is easy to use and internationalizable, and that supports dynamic (runtime) type safety. No VM modifications are necessary.

      Examples

      I'll introduce the language feature by way of an example.

      package java.text;

      class MessageFormat {
          public static String format(String pattern, Object[] arguments...)
          {
              // body omitted
          }
      }

      This shows one possible way to modify an existing class to take advantage of the new language facility. This existing method has been modified by adding the new ellipsis token "..." to the declaration. The resulting method appears identical from the point of view of the VM, but the compiler allows a new invocation syntax:

      import java.text.MessageFormat;
      import java.io.PrintStream;
      class Test {
          public static void test(PrintStream out, String[] args) {
              // existing invocation syntax
              out.println(MessageFormat.format("Args are {0} {1} {2}",
           args));
              // new invocation syntax
              out.println(MessageFormat.format("Names are {0} {1} {2}",
                                               "Neal", "Josh", "Mark"));
          }
      }

      This may not appear to be much of an advantage, but in real applications that have been internationalized a fair bit of scaffolding typically exists to simplify what would have been required before this extension. Typical clients simulate varargs by declaring a series of overloaded methods, with one, two, three, etc additional arguments. As an example of the scale of the simplifications that will be possible with the new invocation syntax, see the class com.sun.tools.javac.util.Log in the implementation of javac.

      Synopsis of the Specification

      JLS 8: Formal Parameters

      The syntax for method declarations (JLS 8.4) and constructor declarations (JLS 8.8) are modified to support an ellipsis before the closing paren. A method declared with an ellipsis is required to have an array type as its last formal parameter.

      JLS 8: Overriding

      We would like to require (JLS 8.4.6.1 and 8.4.6.4) that a method that overrides a varargs method is itself declared with an ellipsis. We cannot do that for backward compatibility because retrofitting an existing method with an ellipsis would break its overriders. Instead, in -source 1.5 it would be a warning only; in -source 1.6 (or some later release) it would be enforced as an error.

      JLS 13: Binary Compatibility

      The binary compatibility chapter (JLS 13) is modified to require the new JVM "Varargs" attribute on those methods that were declared with an ellipsis an on no others. Or perhaps this belongs in the JVM specification.

      JLS 15: Overload Resolution

      Background: Overload resolution (JLS 15.12) must be modified to support boxing and unboxing conversions. Those changes require using a two-pass overload resolution algorithm. The first pass is for compatibility, and excludes boxing conversions and unboxing conversions. This ensures that existing methods and method invocations are unchanged in their semantic interpretation. Only when the first pass finds no applicable methods does the second pass take place, which considers boxing and unboxing conversions as well.

      We further modify this new overload resolution algorithm for varargs. The first pass ignores ellipses in the methods under consideration, even when the methods have been retrofitted for varargs, ensuring backward compatibility. The second pass allows a sequence of arguments to match the trailing array formal parameter of a method declared with an ellipsis when the values can be converted to the element type of the array.

      As now, overload resolution selects among the candidates by finding the most specific method. The meta rule is that one method is more specific than another if all arguments that could be accepted by the one could be accepted by the other. These new rules allow the possibility that two (or more) methods are more specific than each other; this is considered an ambiguity and results in a compile-time error.

      JLS 15: Runtime evaluation of method invocation

      Argument evaluation (JLS 15.12.4.2) must be modified to specify allocating an array and initializing its elements from the relevant arguments if this is necessary to match the invoked method's signature.
      Examples

      class U {
          static void f(String s, int a, short b) {
      System.out.println("a");
          }
          static void f(String s, int a, int b) {
      System.out.println("b");
          }
          static void f(String s, Integer[] args ...) {
      System.out.println("c");
          }
          static void f(String s, Number[] args ...) {
      System.out.println("d");
          }
          static void f(String s, Object[] args ...) {
      System.out.println("e");
          }
          public static void main(String[] args) {
      f("x", 12, (short)13); // a
      f("x", 12, 13); // b
      f("x", 12, 13, 14); // c
      f("x", 12, 13.5); // d
      f("x", 12, true); // e
          }
      }

            gafter Neal Gafter (Inactive)
            ghamiltosunw Graham Hamilton (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: