A
Andreas Leitgeb
This is an idea that occurred to me while reading the Ada vs Java thread,
although not really applying there.
It is about some enhancement that I'd think could go into some future
version of Java (but likely won't anyway). I'm posting it here not
for the purpose of "proposing" it, but to learn about reasons why this
might not be do-able or not worth it... or if someone else has thought
of this already long before.
The point of the idea is, that array variables would be added a static
bit of information, namely a lower bound (0 by default) for the length
of an array that can legally be stored in that variable.
I'll start with an example of what it might look like at source-level:
class Demo {
static int get9th( int[10] a_ia ) {
return a_ia[9]; // guaranteed not to throw an AIOOB-Exception
}
public static void main(String[] args) {
int[20] ia1 = new int[42]; // Fine, it's just a lower bound.
//int[20] ia2 = new int[1]; // this would cause a compile-time error.
// new type[ constant ]'s return value would be type[constant]
// new type[ runtime value ]'s return value would be type[0]
// Later versions of Java could in principle generate a
// stricter return type (higher lower bound), if they can prove
// a higher lower bound for the runtime value, but that might
// impact selection of method overloads (see further below),
// so might not be all that good an idea.
get9th ( ia1 ); // get9th requires "at least 10" and gets "at least 20"
//get9th( new int[5] ); // this would trigger a compile-time error.
int[] ia2 = new int[42]; // or equiv: int[0] ia2 = ...
//foo( ia2 ); // compile-error: no guarantees on length of ia2.
get9th ( (int[10]) ia2 ); // a length-cast: no compiletime error,
// but a runtime-check on the length. if too short: exception
// right at the cast. This is for treating return values from
// old code, that might have provided length-guarantees in the
// documentation.
// not exactly a design-goal, but a dead giveaway:
if ( ia2 instanceof int[40] ) { ... }
}
}
I believe such a change would be source-compatible, but might require
some severe changes at the bytecode/class-file-format level, to allow
to specify such a lower bound in a type signature. Such a change should
be possible in a way, that old class-files can still be used. e.g.:
get9th
]10I)I (currently without bounds: get9th
[I)I )
Methods could overload others just for different length-bounds.
The one with the largest provably satisfyable length-bound would be
chosen among those with otherwise matching signature.
I believe that there will be no issue about contravariance with this
scenario, thus no need to ever specify upper-bounds. If I'm missing
something, I'd be interested to know.
Any technical flaws so far?
One reason that might thwart it could be, that arrays are already
a step-child of Java (generics), so anything about improving on
them may be seen as a down-side, generally, for conceivably making
them more safe, thus more inviting to be used.
Another one could be, that ArrayIndexOutOfBoundsExceptions are
not currently perceived as a problem that could be alleviated
by static checks, anyway.
although not really applying there.
It is about some enhancement that I'd think could go into some future
version of Java (but likely won't anyway). I'm posting it here not
for the purpose of "proposing" it, but to learn about reasons why this
might not be do-able or not worth it... or if someone else has thought
of this already long before.
The point of the idea is, that array variables would be added a static
bit of information, namely a lower bound (0 by default) for the length
of an array that can legally be stored in that variable.
I'll start with an example of what it might look like at source-level:
class Demo {
static int get9th( int[10] a_ia ) {
return a_ia[9]; // guaranteed not to throw an AIOOB-Exception
}
public static void main(String[] args) {
int[20] ia1 = new int[42]; // Fine, it's just a lower bound.
//int[20] ia2 = new int[1]; // this would cause a compile-time error.
// new type[ constant ]'s return value would be type[constant]
// new type[ runtime value ]'s return value would be type[0]
// Later versions of Java could in principle generate a
// stricter return type (higher lower bound), if they can prove
// a higher lower bound for the runtime value, but that might
// impact selection of method overloads (see further below),
// so might not be all that good an idea.
get9th ( ia1 ); // get9th requires "at least 10" and gets "at least 20"
//get9th( new int[5] ); // this would trigger a compile-time error.
int[] ia2 = new int[42]; // or equiv: int[0] ia2 = ...
//foo( ia2 ); // compile-error: no guarantees on length of ia2.
get9th ( (int[10]) ia2 ); // a length-cast: no compiletime error,
// but a runtime-check on the length. if too short: exception
// right at the cast. This is for treating return values from
// old code, that might have provided length-guarantees in the
// documentation.
// not exactly a design-goal, but a dead giveaway:
if ( ia2 instanceof int[40] ) { ... }
}
}
I believe such a change would be source-compatible, but might require
some severe changes at the bytecode/class-file-format level, to allow
to specify such a lower bound in a type signature. Such a change should
be possible in a way, that old class-files can still be used. e.g.:
get9th
Methods could overload others just for different length-bounds.
The one with the largest provably satisfyable length-bound would be
chosen among those with otherwise matching signature.
I believe that there will be no issue about contravariance with this
scenario, thus no need to ever specify upper-bounds. If I'm missing
something, I'd be interested to know.
Any technical flaws so far?
One reason that might thwart it could be, that arrays are already
a step-child of Java (generics), so anything about improving on
them may be seen as a down-side, generally, for conceivably making
them more safe, thus more inviting to be used.
Another one could be, that ArrayIndexOutOfBoundsExceptions are
not currently perceived as a problem that could be alleviated
by static checks, anyway.