PROPOSAL: Simplified Varargs Method Invocation (original) (raw)
Bob Lee crazybob at crazybob.org
Thu Mar 5 17:30:00 PST 2009
- Previous message: PROPOSAL: Multiple switch expressions and case ranges
- Next message: PROPOSAL: Simplified Varargs Method Invocation
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Simplified Varargs Method Invocation AUTHOR: Bob Lee
*OVERVIEW * FEATURE SUMMARY: When a programmer tries to invoke a varargs (variable arity) method with a non-reifiable varargs type, the compiler currently generates an "unsafe operation" warning. This proposal moves the warning from the call site to the method declaration.
MAJOR ADVANTAGE: Safely and significantly reduces the total number of warnings reported to and suppressed by programmers. Reduces programmer confusion. Enables API designers to use varargs.
MAJOR BENEFIT: Plugs a leaky abstraction. Creating an array when you call a varargs method is an implementation detail that we needn't expose to users. Addresses a well known "gotcha" encountered when you mix varargs and generics. Most programmers are surprised to find out you can only clear this warning by suppressing it (especially considering we introduced varargs and generics in the same language update); they waste time looking for alternatives that don't exist. Google Code Search finds almost 90k callers of Arrays.asList() (http://tinyurl.com/dept4d). We could safely suppress the warning once and for all on asList()'s declaration instead of unnecessarily warning every caller that uses a non-reifiable type.
MAJOR DISADVANTAGE: The compiler will generate a warning for a method declaration whether or not someone actually calls the method with a non-reifiable type. Allows loss of type safety if the varargs method suppresses the warning and uses the varargs array unsafely.
ALTERNATIVES: a) Don't mix varargs with generics. Use the more verbose and less straightforward but warning-free builder pattern. Most API designers choose this route. b) Improve the warning message. Current message: "uses unchecked or unsafe operations" c) Reify generics. d) Introduce a second varargs syntax (perhaps using "...." instead of "...") that uses List instead of T[]. e) Defile the type system.
Note: This proposal doesn't preclude any of these other approaches.
*EXAMPLES * Before this change:
static List asList(T... elements) { ... }
static List<Callable> stringFactories() { Callable a, b, c; ... *// Warning: **"uses unchecked or unsafe operations"* return asList(a, b, c); }
After this change:
*// Warning: **"enables unsafe generic array creation"* static List asList(T... elements) { ... }
static List<Callable> stringFactories() { Callable a, b, c; ... return asList(a, b, c); }
If asList() prohibits storing elements that aren't of type T in the elements array, we can safely suppress the warning:
*@SuppressWarnings("generic-varargs") // Ensures only values of type T can be stored in elements.
- static List asList(T... elements) { ... }
*DETAILS * SPECIFICATION: When compiling code that calls a varargs method with a non-reifiable varargs element type, if the target method was compiled targeting Java 7 or later, the compiler needn't generate a warning for the caller. When compiling a varargs method that could accept a non-reifiable varargs type, the compiler should generate a warning on the varargs method declaration. A varargs type is non-reifiable if it contains a type variable anywhere in its signature. For a varargs argument of type T, the programmer can safely suppress the warning using @SuppressWarnings("generic-varargs") so long as the varargs method ensures that only elements of type T can be stored in the varargs array.
COMPILATION: Tools should no longer generate a warning for varargs method callers. Instead, they should generate a warning for varargs method declarations that support non-reifiable types.
TESTING: Compile test programs and ensure that the compiler generates the expected warnings.
LIBRARY SUPPORT: Suppress warnings on the following varargs methods in the JDK:
- Arrays.asList(T... a)
- Collections.addAll(Collection<? super T> c, T... elements)
- EnumSet.of(E first, E... rest)
REFLECTIVE APIS: n/a
OTHER CHANGES: n/a
MIGRATION: Existing callers may be able to remove @SuppressWarnings("unchecked") from their code. Existing libraries should add @SuppressWarnings("generic-varargs") to methods with signatures containing non-reifiable varargs types.
*COMPATIBILITY * BREAKING CHANGES: None
EXISTING PROGRAMS: If you recompile an existing program with "-target 7", the compiler will generate warnings for method declarations containing non-reifiable varargs types.
*REFERENCES * EXISTING BUGS: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6227971
JLS Section 15.12.4.2 "Evaluate Arguments" ( http://java.sun.com/docs/books/jls/third_edition/html/expressions.html)
"If the method being invoked is a variable arity method (ยง8.4.1)<http://java.sun.com/docs/books/jls/third_edition/html/classes.html#38698>m, it necessarily has n>0 formal parameters. The final formal parameter of m necessarily has type T[] for some T, and m is necessarily being invoked with k0 actual argument expressions.
If m is being invoked with kn actual argument expressions, or, if m is being invoked with k=n actual argument expressions and the type of the kth argument expression is not assignment compatible with T[], then the argument list (e1, ... , en-1, en, ...ek) is evaluated as if it were written as (e1, ..., en-1, new T[]{en, ..., ek}).
The argument expressions (possibly rewritten as described above) are now evaluated to yield argument values. Each argument value corresponds to exactly one of the method's n formal parameters."
Angelika Langer's Java Generics FAQ, "Why does the compiler sometimes issue an unchecked warning when I invoke a 'varargs' method?" ( http://tinyurl.com/8w2dk)
Josh Bloch's "Effective Java" 2nd Edition, page 120 ( http://tinyurl.com/chtgbd)
Alex Miller's blog, "Generics puzzler - array construction" ( http://tech.puredanger.com/2007/02/27/generics-array-construction/)
"Java Generic and Collections", page 95 (http://tinyurl.com/c53pnu)
- Previous message: PROPOSAL: Multiple switch expressions and case ranges
- Next message: PROPOSAL: Simplified Varargs Method Invocation
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]