Proposal: Accepting a subclass as an element type in a for loop
Jean-Louis Ardoint
jlardoint at ilog.fr
Tue Mar 31 05:55:45 PDT 2009
I'm maybe a bit too late. Here's my proposal anyway.
-- Jean-Louis Ardoint
Accepting a subclass as an element type in a for loop
AUTHOR(S): Jean-Louis Ardoint
OVERVIEW
FEATURE SUMMARY
Add a filtering and downcast capability to the enhanced for statement
(a.k.a for each).
MAJOR ADVANTAGE
It should reduce the number of lines of code and depth of nesting in
loops. The resulting code would be more readable that what is done
currently to achieve the same goal. The meaning of such a loop is quite
obvious.
MAJOR BENEFIT
Better readability and expressiveness.
MAJOR DISADVANTAGE
More complexity in the compiler to generate a little bit more bytecode.
ALTERNATIVE
You can currently the same thing, yet it means adding an extra if
statement and an intermediate variable to be cast.
EXAMPLES
Here is a small not very interesting example of such a enhanced for
loop:
Shape[] shapes = ...;
for (Shape s : shapes)
drawShape(s);
If for a reason you would need to draw only the rectangles, you would
need to write:
for (Shape s : shapes) {
if (s instanceof Rectangle)
drawRectangle((Rectangle)s);
}
This is not very aesthetic. If only the for loop would directly accept a
subclass as the element type and do the type checking and downcast, we
could be able to write:
for (Rectangle r : shapes)
drawRectangle(r);
Note that there is a subtlety w.r.t. the handling of nulls. See
Compilation below for more details
DETAILS
SPECIFICATION:
The grammar is unchanged. The equivalence between an enhanced for loop
and a regular for loop has to be changed in JLS 14.14.2.
COMPILATION:
The way enhanced loop are translated into bytecode would change
depending on whether the loop variable type is a subclass of the
iterable or array element type.
If the loop variable type is a subclass, then the loop is equivalent to:
For an expression returning Iterable<C>:
Iterable<C> cs...
for (I #i = cs.iterator(); #i.hasNext(); ) {
C #c = #i.next();
if (#c == null || #c instanceof D) {
D d = (C)#c;
...
}
}
For an array:
C[] ca...
for (int i = 0; i < ca.length; i++) {
C #c = ca[i];
if (#c == null || #c instanceof D) {
D d = (C)#c;
...
}
}
Note that we need to test against null to keep the same behavior as the
regular enhanced for loop.
TESTING:
This feature can be tested in the same way the enhanced for loop is
tested.
LIBRARY SUPPORT:
There is no need for library support.
REFLECTIVE APIS:
No updates to the reflection APIs are needed.
OTHER CHANGES:
No other changes are needed.
MIGRATION:
Migration of existing enhanced for loop can be done if one desires so.
COMPATIBILITY
BREAKING CHANGES:
This feature would not break any existing programs, since the new
feature only permits more code to be parsed than before.
EXISTING PROGRAMS:
Class file format does not change, so existing programs can use class
files compiled with the new feature without problems.
More information about the coin-dev
mailing list