From: Mike Schilling on
Lew wrote:
> Mike Schilling wrote:
>> Lew wrote:
>>> Roedy Green wrote:
>>>> That is one of my conjectures, that type erasure was a
>>>> wrong-headed
>>>> idea. It weakened and complicated generics too much. Surely, it
>>>> is
>>>> not inherent to the notion that containers should be type safe.
>>> I like type erasure. It keeps one from the temptation to use
>>> genericity as an operational concept as opposed to a declarative
>>> one.
>>
>> I almost know what this means, but every time I think I've grasped
>> it, my hand seems to be empty. Could you elaborate?
>
> As it stands, generics provide a compile-time contract for
> declarations about type relationships. In order to get run-time
> behavior, i.e., operational use of type information you need to
> provide a Class object; type parameters don't permit any run-time
> operations.
> The result is that generics provide compile-time assertions that
> code
> will not throw a ClassCastException or other type-related problem.
> Erasure guarantees that this safety carries no run-time overhead.
>
> Run-time generics would sacrifice this efficiency and tempt us to
> patch holes in the type analysis with procedural hacks. Instead of
> analyzing the types we'd coerce them. Java still lets you do
> run-time type tricks with a type token (Class object), but type
> parameters are reserved for assertions about type relationships.
> This forces us to deal with type problems at compile time.

Got it. You don't want people codeing

if (T.class.isSubclassOf(Number.class))

Is this really an issue, though? In principle you could do that with

void method( Object[] o)
{
if (o.getClass().getComponentType()
isSubclassOf(Number.class))
...
But I've never seen anything like that.


From: Peter Duniho on
On Sat, 10 Oct 2009 00:05:37 -0700, Mike Schilling
<mscottschilling(a)hotmail.com> wrote:

> Erasure is needed for compatibility with the non-generic version of
> the type, and that's the only reason it exists. If generics had been
> present from the beginning, the type parameters would be first-class
> parts of the type, just as they are for arrays. (And just as they
> are in .NET, where generics were used only in newly introduced
> classes.)

Though, .NET illustrates that an alternative approach would have been to
simply create a new, parallel group of classes supporting generics, rather
than to insist that the old classes be reusable via generics.

I believe you're correct with respect to the motivation for having type
erasure, but it wasn't a mandatory feature by any means.

Pete
From: Peter Duniho on
On Sat, 10 Oct 2009 07:54:41 -0700, Lew <noone(a)lewscanon.com> wrote:

> Roedy Green wrote:
>> That is one of my conjectures, that type erasure was a wrong-headed
>> idea. It weakened and complicated generics too much. Surely, it is not
>> inherent to the notion that containers should be type safe.
>
> I like type erasure. It keeps one from the temptation to use genericity
> as an operational concept as opposed to a declarative one.

I agree that having removed the temptation, certain code is better for
having prevented certain programmers from having written code that way.

But, type erasure prevents other useful aspects of generics. One in
particular is the inability to use any value types with generics. They
always have to be boxed, because the underlying type is always Object.
Another less-common need is to legitimately need to know the exact type,
including the type parameters; just as "instanceof" should be used
sparingly, so too would run-time information about a generic type, but
just as there are legitimate reasons for using "instanceof", completely
prohibiting access at run-time to generic type information prevents those
rare legitimate uses.

As usual, the question isn't so much "is this the absolute, correct way to
do things", but rather "is it more important to protect one's foot from
being shot, or to allow more legitimate complex behaviors at the expense
of the potential for foot-shooting?"

Pete
From: Thomas Pornin on
According to Roedy Green <see_website(a)mindprod.com.invalid>:
> Surely, it is not inherent to the notion that containers should be
> type safe.

The perceived complexity of Java-like generics for containers is
inherent to the notion of trying to build type-safe containers with only
static typing. That's what type erasure is about: everything occurs at
compile-time. When trying to avoid runtime overhead, the compile-time
behaviour becomes more complex and somewhat difficult to grasp. An
extreme case is the ML family of languages (e.g. OCaml) which have no
dynamic typing at all, and yet provide strong, unescapable types.

A "simple", type-safe container is easy: simply let the runtime system
know about the element type, and perform dynamic type checks on write
access (in many situations these can be optimized away). That is exactly
what happens with Java arrays.

The Java designers are apparently very reluctant to extend the
_language_ in ways which imply non-trivial modifications of the _virtual
machine_. They really prefer it when language extensions are handled
with the compiler only, possibly with some additional library code,
itself written in Java with as little native code as possible. Thus,
when ArrayList was invented, it was added as some library code, without
needing any change to the JVM itself. And, similarly, when ArrayList had
to become type-safe, this was done with generics which again are handled
entirely by the compiler (all the JVM has to know is that a given Class
has type parameters, but it needs not know what the compiler knew about
those parameters). There is a trade-off: type-erasure generics are not
as easy to use as runtime type parameters, and there are a few things
that they cannot do (e.g. you cannot implement ArrayList itself without
at least one warning about an unchecked conversion, unless you fool the
compiler with some native code); on the other hand, porting a JVM from
Java-1.4 to Java-5 is easy, at least for the part about generics: there
is almost no work to do.

(This trend is not absolute. E.g. java.lang.ref.WeakReference was added
at some point (Java-1.2 if I remember correctly) and that one requires
a fair amount of tricky support from the GC implementation.)

If Sun was to design Java again now, they would probably integrate type
parameters with runtime support. There would not be this irksome
distinction between arrays and lists.


--Thomas Pornin
From: Mike Schilling on
Peter Duniho wrote:
> On Sat, 10 Oct 2009 00:05:37 -0700, Mike Schilling
> <mscottschilling(a)hotmail.com> wrote:
>
>> Erasure is needed for compatibility with the non-generic version of
>> the type, and that's the only reason it exists. If generics had
>> been
>> present from the beginning, the type parameters would be
>> first-class
>> parts of the type, just as they are for arrays. (And just as they
>> are in .NET, where generics were used only in newly introduced
>> classes.)
>
> Though, .NET illustrates that an alternative approach would have
> been
> to simply create a new, parallel group of classes supporting
> generics, rather than to insist that the old classes be reusable via
> generics.

It's technically feasible, sure, but given the amount of existing Java
code when 1.5 was introduced, imagine the dumbfoundment with which a
new and incompatible set of, e.g. collections classes (and, far worse,
collection interfaces) would have been greeted.