Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > Type erasure bug?

Reply
Thread Tools

Type erasure bug?

 
 
Safalra
Guest
Posts: n/a
 
      08-28-2005
Consider the following code:

Vector<String> s=new Vector<String>(10);
Vector o=s;
o.add(new Object());
Object p=s.get(0);

Obviously this gives an unchecked warning about the second line.
Because of type erasure the third line doesn't cause a run-time
exception either. What surprises me is that the fourth line doesn't
cause a class cast exception, despite accessing the Vector through s. I
presume internally type erasure turns it into:

Object p=(Object)(String)s.get(0);

Which the compiler simplifies to:

Object p=s.get(0);

Is my understanding of this correct, and do people here regard this a
bug in the compiler, or just another consequence of allowing unchecked
exceptions in your code?

(I discovered this while writing an article for a friend of mine who
isn't a fan of Java - you can read it at
http://www.safalra.com/programming/java/wrongerasure/ but remember that
I *do* actually like Java in general, I just dislike certain features.)

--
Safalra (Stephen Morley)
http://www.safalra.com/programming/

 
Reply With Quote
 
 
 
 
Thomas Hawtin
Guest
Posts: n/a
 
      08-28-2005
Safalra wrote:
> Consider the following code:
>
> Vector<String> s=new Vector<String>(10);
> Vector o=s;
> o.add(new Object());
> Object p=s.get(0);
>
> Obviously this gives an unchecked warning about the second line.
> Because of type erasure the third line doesn't cause a run-time
> exception either. What surprises me is that the fourth line doesn't
> cause a class cast exception, despite accessing the Vector through s. I
> presume internally type erasure turns it into:
>
> Object p=(Object)(String)s.get(0);
>
> Which the compiler simplifies to:
>
> Object p=s.get(0);
>
> Is my understanding of this correct, and do people here regard this a
> bug in the compiler, or just another consequence of allowing unchecked
> exceptions in your code?


If you try to subvert generic types on your own head be it. It seems
reasonable to avoid unnecessary casts. It would be even more expensive
to check super bounds.

Beta versions of 5.0 had a bug where the removal of unnecessary casts
went a little too far. If you had List<char[]> and then passed the
elements to System.out.println, it would use System.out.println(Object)
instead of System.out.println(char[]).

Tom Hawtin
--
Unemployed English Java programmer
http://jroller.com/page/tackline/
 
Reply With Quote
 
 
 
 
Raymond DeCampo
Guest
Posts: n/a
 
      08-29-2005
Safalra wrote:
> Consider the following code:
>
> Vector<String> s=new Vector<String>(10);
> Vector o=s;
> o.add(new Object());
> Object p=s.get(0);
>
> Obviously this gives an unchecked warning about the second line.
> Because of type erasure the third line doesn't cause a run-time
> exception either. What surprises me is that the fourth line doesn't
> cause a class cast exception, despite accessing the Vector through s. I
> presume internally type erasure turns it into:
>


Why would assigning anything (except a primitive type, which would cause
a compiler error) to Object ever cause a class cast exception?

Ray

--
XML is the programmer's duct tape.
 
Reply With Quote
 
Thomas G. Marshall
Guest
Posts: n/a
 
      08-29-2005
Raymond DeCampo coughed up:
> Safalra wrote:
>> Consider the following code:
>>
>> Vector<String> s=new Vector<String>(10);
>> Vector o=s;
>> o.add(new Object());
>> Object p=s.get(0);
>>
>> Obviously this gives an unchecked warning about the second line.
>> Because of type erasure the third line doesn't cause a run-time
>> exception either. What surprises me is that the fourth line doesn't
>> cause a class cast exception, despite accessing the Vector through
>> s. I presume internally type erasure turns it into:
>>

>
> Why would assigning anything (except a primitive type, which would
> cause a compiler error) to Object ever cause a class cast exception?



You're missing the OP's point here.

Generics allows you to omit the cast when retrieving values. Given the OP's
vector of strings "s":

String str = s.get(0);

is allowed without requiring the

String str = (String)s.get(0);

cast that you would have to do pre-generics. That cast is "added in". So
the question is what happens in the 4th line of his example:

Object p = s.get(0);

One would think that this might internally become:

Object p = (String)s.get(0);

because of "s" being a generic (Vector of String). That is where the CCE
might have come in. What he has at slot 0 in the vector is a plain old
Object, not a String. So his question is why doesn't this fail.


--
"Well, ain't this place a geographical oddity!
Two weeks from everywhere!"


 
Reply With Quote
 
Mike Schilling
Guest
Posts: n/a
 
      08-29-2005

"Thomas G. Marshall" <(E-Mail Removed). com>
wrote in message news:lmuQe.6198$fP.1084@trndny08...
> Raymond DeCampo coughed up:
>> Safalra wrote:
>>> Consider the following code:
>>>
>>> Vector<String> s=new Vector<String>(10);
>>> Vector o=s;
>>> o.add(new Object());
>>> Object p=s.get(0);
>>>
>>> Obviously this gives an unchecked warning about the second line.
>>> Because of type erasure the third line doesn't cause a run-time
>>> exception either. What surprises me is that the fourth line doesn't
>>> cause a class cast exception, despite accessing the Vector through
>>> s. I presume internally type erasure turns it into:
>>>

>>
>> Why would assigning anything (except a primitive type, which would
>> cause a compiler error) to Object ever cause a class cast exception?

>
>
> You're missing the OP's point here.
>
> Generics allows you to omit the cast when retrieving values. Given the
> OP's vector of strings "s":
>
> String str = s.get(0);
>
> is allowed without requiring the
>
> String str = (String)s.get(0);
>
> cast that you would have to do pre-generics. That cast is "added in". So
> the question is what happens in the 4th line of his example:
>
> Object p = s.get(0);
>
> One would think that this might internally become:
>
> Object p = (String)s.get(0);
>
> because of "s" being a generic (Vector of String). That is where the CCE
> might have come in. What he has at slot 0 in the vector is a plain old
> Object, not a String. So his question is why doesn't this fail.



Mine too. Surely if I wrote

methodX(s.get(0))

and methodX had overloads methodX(String) and methodX(Object), this should
generate

methodX((String)s.get(0))

On the other hand, if methodX only has the overload methodX(Object), the
cast in

methodX((String)s.get(0))

is unnecessary and, it can be argued, should be omitted. Is it the case,
then, that the return type implied by the use of the generic method (i.e.
"get()") determines whether the cast is applied? That seems evil to me,
being the moral equivalent of overloading methods by return type. (And it
would cause an odd bug if the overload methodX(String) were added after the
caller was compiled) But I can't in all honesty say that I've thought this
through.





 
Reply With Quote
 
Chris Uppal
Guest
Posts: n/a
 
      08-29-2005
Mike Schilling wrote:

> Is it the case,
> then, that the return type implied by the use of the generic method (i.e.
> "get()") determines whether the cast is applied? That seems evil to me,
> being the moral equivalent of overloading methods by return type. (And
> it would cause an odd bug if the overload methodX(String) were added
> after the caller was compiled)


I'm not sure if I'm understanding what you consider "evil", but -- although
surprising -- it doesn't seem all that damaging to me. After all the situation
only arises when you mix generic and non-generic code in the same application
/and/ expect the compiler to produce static type safety. Runtime type safety
is still (I think) assured, since the compiler only omits "unnecessary"
casts -- so runtime stuff that /should/ work /does/ work. The only thing
that's omitted is that runtime code that (according to static tests) cannot be
validated is allowed to run (or fail) dynamically, rather than duplicating the
"fail even if it is not actually doing anything illegal" behaviour that the
static type checking enforces.

BTW, don't forget that the signature of the called method is part of the
invokexxx bytecode(s), so if any other methodX(String) were added later, then
that would be "invisible" to the code that was compiled before it existed.

-- chris




 
Reply With Quote
 
Raymond DeCampo
Guest
Posts: n/a
 
      08-29-2005
Thomas G. Marshall wrote:
> Raymond DeCampo coughed up:
>
>>Safalra wrote:
>>
>>>Consider the following code:
>>>
>>>Vector<String> s=new Vector<String>(10);
>>>Vector o=s;
>>>o.add(new Object());
>>>Object p=s.get(0);
>>>
>>>Obviously this gives an unchecked warning about the second line.
>>>Because of type erasure the third line doesn't cause a run-time
>>>exception either. What surprises me is that the fourth line doesn't
>>>cause a class cast exception, despite accessing the Vector through
>>>s. I presume internally type erasure turns it into:
>>>

>>
>>Why would assigning anything (except a primitive type, which would
>>cause a compiler error) to Object ever cause a class cast exception?

>
>
>
> You're missing the OP's point here.


You are correct.

>
> Generics allows you to omit the cast when retrieving values. Given the OP's
> vector of strings "s":
>
> String str = s.get(0);
>
> is allowed without requiring the
>
> String str = (String)s.get(0);
>
> cast that you would have to do pre-generics. That cast is "added in". So
> the question is what happens in the 4th line of his example:
>
> Object p = s.get(0);
>
> One would think that this might internally become:
>
> Object p = (String)s.get(0);
>
> because of "s" being a generic (Vector of String). That is where the CCE
> might have come in. What he has at slot 0 in the vector is a plain old
> Object, not a String. So his question is why doesn't this fail.
>
>


Thanks for the exposition.

Ray

--
XML is the programmer's duct tape.
 
Reply With Quote
 
Safalra
Guest
Posts: n/a
 
      08-30-2005
Mike Schilling wrote:
> "Thomas G. Marshall" <(E-Mail Removed). com>
> wrote in message news:lmuQe.6198$fP.1084@trndny08...
> > [snip]
> > Object p = s.get(0);
> > One would think that this might internally become:
> > Object p = (String)s.get(0);
> > because of "s" being a generic (Vector of String). That is where the CCE
> > might have come in. What he has at slot 0 in the vector is a plain old
> > Object, not a String. So his question is why doesn't this fail.

>
> Mine too. Surely if I wrote
> methodX(s.get(0))
> and methodX had overloads methodX(String) and methodX(Object), this should
> generate
> methodX((String)s.get(0))
> On the other hand, if methodX only has the overload methodX(Object), the
> cast in
> methodX((String)s.get(0))
> is unnecessary and, it can be argued, should be omitted. Is it the case,
> then, that the return type implied by the use of the generic method (i.e.
> "get()") determines whether the cast is applied? That seems evil to me,
> being the moral equivalent of overloading methods by return type.


I don't understand in what way you consider these equivalent.

--
Safalra (Stephen Morley)
http://www.safalra.com/programming/

 
Reply With Quote
 
Thomas G. Marshall
Guest
Posts: n/a
 
      08-30-2005
Mike Schilling coughed up:
> "Thomas G. Marshall"
> <(E-Mail Removed). com> wrote in
> message news:lmuQe.6198$fP.1084@trndny08...


....[rip]...

>> One would think that this might internally become:
>>
>> Object p = (String)s.get(0);
>>
>> because of "s" being a generic (Vector of String). That is where
>> the CCE might have come in. What he has at slot 0 in the vector is
>> a plain old Object, not a String. So his question is why doesn't
>> this fail.

>
>
> Mine too. Surely if I wrote
>
> methodX(s.get(0))
>
> and methodX had overloads methodX(String) and methodX(Object), this
> should generate
>
> methodX((String)s.get(0))
>
> On the other hand, if methodX only has the overload methodX(Object),
> the cast in
>
> methodX((String)s.get(0))
>
> is unnecessary and, it can be argued, should be omitted. Is it the
> case, then, that the return type implied by the use of the generic
> method (i.e. "get()") determines whether the cast is applied? That
> seems evil to me, being the moral equivalent of overloading methods
> by return type.


I'm not thrilled with hardly any of this generics business. As I've said
before, it really seems the wrong solution, and generics should have been a
full-blown runtime thing, backward compatibility be damned.

However, this particular blemish doesn't bother me as much as it seems to
you: it seems as if it is a compiler simply making a later pass over the
code and removing broken casts. (maybe).

That's the problem with half-baked solutions. They tend to necessitate
plaster and spackle in various places.


> (And it would cause an odd bug if the overload
> methodX(String) were added after the caller was compiled) But I
> can't in all honesty say that I've thought this through.



 
Reply With Quote
 
Roedy Green
Guest
Posts: n/a
 
      08-31-2005
On 28 Aug 2005 08:58:45 -0700, "Safalra" <(E-Mail Removed)> wrote or
quoted :

>Vector<String> s=new Vector<String>(10);
>Vector o=s;
>o.add(new Object());
>Object p=s.get(0);


I would read it this way:

You have made a deal with Javac. You have said the Vector will
contain only Strings. If there is any unchecked code, you accept the
compiler's warning and agree to keep the contract manually to let only
Strings into the Vector.

So the compiler then looks at the line

Object p=s.get(0);

It says to itself, s contains only Strings. Therefore get must return
a String. A String is a species of Object, so no cast is needed.

Further, from a type erasure point of view, s at run time contains
only Objects (or subclasses) absolutely guaranteed, so no cast is
necessary.


--
Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Dynamic Casting with Generics: Type Erasure Problems William Java 3 03-04-2011 06:08 PM
Dynamic Casting with Generics: Type Erasure Problems William Java 5 03-03-2011 06:22 PM
Generics and type erasure Martin Lorentzson Java 2 11-06-2006 09:02 PM
Generics: struggling against type erasure... z-man Java 8 10-09-2006 07:53 AM
Java Generics, Type Erasure and Frameworks Sebastian Millies Java 1 10-07-2004 10:10 AM



Advertisments