Will the new Generics mechanism still use runtime casting?

Discussion in 'Java' started by Dave Stallard, Sep 29, 2003.

  1. I have a question about the new Generics mechanism which articles I've
    read have left me still a little uncertain about. Suppose you have
    (say) a List whose elements are of class Foo. Objects of this type
    would be declared as:

    List<Foo> x = new List<Foo>();

    Now suppose you do lookup or iteration:

    Foo f = x.get(0);

    With Generics, there is no longer a need to insert an explicit cast.
    BUT, underneath the hood in the implementation, is there a still a cast
    being performed at runtime in a statement like the one above? I
    certainly hope not, since I know that runtime casts introduce a
    performance penalty.

    Dave
    Dave Stallard, Sep 29, 2003
    #1
    1. Advertising

  2. Dave Stallard

    Skippy Guest

    > With Generics, there is no longer a need to insert an explicit cast.
    > BUT, underneath the hood in the implementation, is there a still a cast
    > being performed at runtime in a statement like the one above?


    Yep, generics are there to inform the compiler and ease the class-casting
    pain, but the bytecode output is the same.
    Skippy, Sep 30, 2003
    #2
    1. Advertising

  3. Dave Stallard

    xarax Guest

    "Skippy" <0spam.nl> wrote in message news:<blaf8a$fpi$>...
    > > With Generics, there is no longer a need to insert an explicit cast.
    > > BUT, underneath the hood in the implementation, is there a still a cast
    > > being performed at runtime in a statement like the one above?

    >
    > Yep, generics are there to inform the compiler and ease the class-casting
    > pain, but the bytecode output is the same.


    A properly implemented JVM can perform a cast or instanceof test
    in constant time, regardless of the complexity of the inheritance
    graph.

    Don't worry about it. Computers exist for the convenience
    of people, not vice versa. The big benefit of Generics is
    that the compiler knows for certain that the cast will work
    or not work. If the cast won't work, then you see a compile
    error and can fix your code sooner than waiting for a runtime
    exception.
    xarax, Sep 30, 2003
    #3
  4. Dave Stallard

    Phillip Lord Guest

    >>>>> "xarax" == xarax <> writes:

    xarax> "Skippy" <0spam.nl> wrote in message
    xarax> news:<blaf8a$fpi$>...
    >> > With Generics, there is no longer a need to insert an explicit
    >> > cast. BUT, underneath the hood in the implementation, is there
    >> > a still a cast being performed at runtime in a statement like
    >> > the one above?

    >>
    >> Yep, generics are there to inform the compiler and ease the
    >> class-casting pain, but the bytecode output is the same.


    xarax> A properly implemented JVM can perform a cast or instanceof
    xarax> test in constant time, regardless of the complexity of the
    xarax> inheritance graph.


    Actually I don't think that it can, unless it pre-calculates a
    transitive closure. Which it can't do in constant time.

    xarax> Don't worry about it. Computers exist for the convenience of
    xarax> people, not vice versa. The big benefit of Generics is that
    xarax> the compiler knows for certain that the cast will work or not
    xarax> work. If the cast won't work, then you see a compile error
    xarax> and can fix your code sooner than waiting for a runtime
    xarax> exception.


    No. The "cast" can fail. And if it does you will get a
    CastClassException where no Cast exists in code, only in byte code.

    So for instance....

    // generics working well...
    List<Frame> frameList = new List<Frame>();
    frameList.add( new Frame() );
    Frame frame = frameList.get( 0 )


    // this is an up cast. List<Frame> is a subtype of List...
    List list = (List)frameList;
    list.add( new Object() );
    Object object = list.get( 1 );

    //and this bit fails
    frameList.get( 1 );


    So in fact while generics mean that you don't have to put casts where
    you used to, but they offer you few guarantees. At best I think they
    should be considered something like more auto-boxing...that is more
    syntactic sugar, than stronger type checking.

    Phil
    Phillip Lord, Sep 30, 2003
    #4
  5. Dave Stallard

    Chris Uppal Guest

    xarax wrote:

    > The big benefit of Generics is
    > that the compiler knows for certain that the cast will work
    > or not work.


    Well, not exactly. It's more that the use of Generics persuades the compiler
    that the cast *should* work, so it doesn't insist on whinging about it.
    Whether it will *actually* work is another matter altogether.

    -- chris
    Chris Uppal, Sep 30, 2003
    #5
  6. (xarax) writes:

    > The big benefit of Generics is that the compiler knows for certain
    > that the cast will work or not work. If the cast won't work, then
    > you see a compile error and can fix your code sooner than waiting
    > for a runtime exception.


    Well, sort of. The specialized collection can still be cast to a
    non-specialized one, much like you can cast away constness in C++.
    Tor Iver Wilhelmsen, Sep 30, 2003
    #6
  7. Phillip Lord wrote:

    >>>>>>"xarax" == xarax <> writes:

    >
    >
    > xarax> "Skippy" <0spam.nl> wrote in message
    > xarax> news:<blaf8a$fpi$>...
    > >> > With Generics, there is no longer a need to insert an explicit
    > >> > cast. BUT, underneath the hood in the implementation, is there
    > >> > a still a cast being performed at runtime in a statement like
    > >> > the one above?
    > >>
    > >> Yep, generics are there to inform the compiler and ease the
    > >> class-casting pain, but the bytecode output is the same.

    >
    > xarax> A properly implemented JVM can perform a cast or instanceof
    > xarax> test in constant time, regardless of the complexity of the
    > xarax> inheritance graph.
    >
    >
    > Actually I don't think that it can, unless it pre-calculates a
    > transitive closure. Which it can't do in constant time.


    I tried measuring how long it actually takes with 1.4.2. A cast from
    Object --> Integer appeared to take 0.5ns on my 3.06GHz P4. So whatever
    they are doing it is astonishingly quick.

    Mark Thornton
    Mark Thornton, Sep 30, 2003
    #7
  8. Take a look at Sun's presentation on Generics, pages 22 and 23 at
    http://servlet.java.sun.com/javaone/conf/sessions/2733/0-sf2001.jsp (Sorry,
    I could not copy the text here)

    Based on that the following line from your sample

    list.add( new Object() );

    will generate (I quote) "compile-time unchecked warning".

    I am not absolutely sure what this means.
    If it was up to me I would like to see an error on the assignment

    List list = (List)frameList;

    making List<Frame> incompatible with List<Object>.

    In fact why should List<A> be a subclass of List<B> if A is subclass of B?
    Sure you need to be able to put objects of type A into List<B> and this does
    not create any issues,
    but what is the use of assigning the List<A> itself to variable of type
    List<B>?

    Regards,
    Dobromir


    "Phillip Lord" <> wrote in message
    news:...
    > >>>>> "xarax" == xarax <> writes:

    >
    > xarax> "Skippy" <0spam.nl> wrote in message
    > xarax> news:<blaf8a$fpi$>...
    > >> > With Generics, there is no longer a need to insert an explicit
    > >> > cast. BUT, underneath the hood in the implementation, is there
    > >> > a still a cast being performed at runtime in a statement like
    > >> > the one above?
    > >>
    > >> Yep, generics are there to inform the compiler and ease the
    > >> class-casting pain, but the bytecode output is the same.

    >
    > xarax> A properly implemented JVM can perform a cast or instanceof
    > xarax> test in constant time, regardless of the complexity of the
    > xarax> inheritance graph.
    >
    >
    > Actually I don't think that it can, unless it pre-calculates a
    > transitive closure. Which it can't do in constant time.
    >
    > xarax> Don't worry about it. Computers exist for the convenience of
    > xarax> people, not vice versa. The big benefit of Generics is that
    > xarax> the compiler knows for certain that the cast will work or not
    > xarax> work. If the cast won't work, then you see a compile error
    > xarax> and can fix your code sooner than waiting for a runtime
    > xarax> exception.
    >
    >
    > No. The "cast" can fail. And if it does you will get a
    > CastClassException where no Cast exists in code, only in byte code.
    >
    > So for instance....
    >
    > // generics working well...
    > List<Frame> frameList = new List<Frame>();
    > frameList.add( new Frame() );
    > Frame frame = frameList.get( 0 )
    >
    >
    > // this is an up cast. List<Frame> is a subtype of List...
    > List list = (List)frameList;
    > list.add( new Object() );
    > Object object = list.get( 1 );
    >
    > //and this bit fails
    > frameList.get( 1 );
    >
    >
    > So in fact while generics mean that you don't have to put casts where
    > you used to, but they offer you few guarantees. At best I think they
    > should be considered something like more auto-boxing...that is more
    > syntactic sugar, than stronger type checking.
    >
    > Phil
    Dobromir Gaydarov, Oct 1, 2003
    #8
  9. Dave Stallard

    Chris Uppal Guest

    Dobromir Gaydarov wrote:

    > In fact why should List<A> be a subclass of List<B> if A is subclass of B?
    > Sure you need to be able to put objects of type A into List<B> and this
    > does not create any issues,
    > but what is the use of assigning the List<A> itself to variable of type
    > List<B>?


    Presumably for the same reasons (good or bad) as Java allows asssignment of a
    String[] to an Object[] variable.

    -- chris
    Chris Uppal, Oct 1, 2003
    #9
  10. Dave Stallard

    Neal Gafter Guest

    Chris Uppal wrote:
    > Dobromir Gaydarov wrote:
    >
    >
    >>In fact why should List<A> be a subclass of List<B> if A is subclass of B?
    >>Sure you need to be able to put objects of type A into List<B> and this
    >>does not create any issues,
    >>but what is the use of assigning the List<A> itself to variable of type
    >>List<B>?

    >
    >
    > Presumably for the same reasons (good or bad) as Java allows asssignment of a
    > String[] to an Object[] variable.


    The reason was that generics were not available for expressing methods like
    sort() that should operate on a variety of array types. That reason simply does
    not apply in the presence of generics. The covariance of Java arrays is a flaw
    in the type system not to be admired and imitated.

    If A is a subclass of B, then both List<A> and List<B> are subtypes of
    List<? extends B>
    using the recently introduced "wildcards" notation.

    -Neal
    Neal Gafter, Oct 1, 2003
    #10
  11. Dave Stallard

    Neal Gafter Guest

    Casts to interface types are slower on many VMs.

    Mark Thornton wrote:
    > Phillip Lord wrote:
    >
    >>>>>>> "xarax" == xarax <> writes:

    >>
    >>
    >>
    >> xarax> "Skippy" <0spam.nl> wrote in message
    >> xarax> news:<blaf8a$fpi$>...
    >> >> > With Generics, there is no longer a need to insert an explicit
    >> >> > cast. BUT, underneath the hood in the implementation, is there
    >> >> > a still a cast being performed at runtime in a statement like
    >> >> > the one above?
    >> >>
    >> >> Yep, generics are there to inform the compiler and ease the
    >> >> class-casting pain, but the bytecode output is the same.

    >>
    >> xarax> A properly implemented JVM can perform a cast or instanceof
    >> xarax> test in constant time, regardless of the complexity of the
    >> xarax> inheritance graph.
    >>
    >>
    >> Actually I don't think that it can, unless it pre-calculates a
    >> transitive closure. Which it can't do in constant time.

    >
    >
    > I tried measuring how long it actually takes with 1.4.2. A cast from
    > Object --> Integer appeared to take 0.5ns on my 3.06GHz P4. So whatever
    > they are doing it is astonishingly quick.
    >
    > Mark Thornton
    >
    Neal Gafter, Oct 1, 2003
    #11
  12. Dave Stallard

    Neal Gafter Guest

    Phillip Lord wrote:
    > No. The "cast" can fail. And if it does you will get a
    > CastClassException where no Cast exists in code, only in byte code.
    >
    > So for instance....
    >
    > // generics working well...
    > List<Frame> frameList = new List<Frame>();
    > frameList.add( new Frame() );
    > Frame frame = frameList.get( 0 )
    >
    >
    > // this is an up cast. List<Frame> is a subtype of List...
    > List list = (List)frameList;
    > list.add( new Object() );
    > Object object = list.get( 1 );
    >
    > //and this bit fails
    > frameList.get( 1 );
    >
    >
    > So in fact while generics mean that you don't have to put casts where
    > you used to, but they offer you few guarantees. At best I think they
    > should be considered something like more auto-boxing...that is more
    > syntactic sugar, than stronger type checking.


    The Java compiler will give you a warning on the list.add() call. If your
    entire application compiles with no such warnings, you are indeed guaranteed not
    to have such failures at runtime.
    Neal Gafter, Oct 1, 2003
    #12
  13. Dave Stallard

    Phillip Lord Guest

    >>>>> "Neal" == Neal Gafter <> writes:

    Neal> Phillip Lord wrote:
    >>// generics working well...
    >>List<Frame> frameList = new List<Frame>();
    >>frameList.add( new Frame() );
    >>Frame frame = frameList.get( 0 )
    >>
    >>
    >>// this is an up cast. List<Frame> is a subtype of List...
    >>List list = (List)frameList;
    >>list.add( new Object() );
    >>Object object = list.get( 1 );
    >>
    >>//and this bit fails
    >>frameList.get( 1 );



    Neal> The Java compiler will give you a warning on the list.add()
    Neal> call. If your entire application compiles with no such
    Neal> warnings, you are indeed guaranteed not to have such failures
    Neal> at runtime.

    Really? Thats interesting. This seems to be new to me. I guess I shall
    have to re-read the spec.

    While I can see how this would work, I wonder whether what you say is
    true in general though. For instance.....


    public void add( List list, Object o )
    {
    list.add( o );
    }

    will this throw a warning, as it can be called as...

    List<Frame> list;
    add( list, new Object() );

    which causes the same difficulty. The general solution to this is to
    make the type coercion go only in one direction. So List<Frame> can
    become List, but it involves cloning, or never allowing you to treat
    the object as List<Frame> again.

    Phil
    Phillip Lord, Oct 1, 2003
    #13
  14. In article <>,
    Neal Gafter <> wrote:
    >
    >The Java compiler will give you a warning on the list.add() call. If your


    I assume it can only do this in the most trivial cases. What I am
    worried about is when I write something along the lines of

    List<Integer> list = new List<Integer>();
    list.add(new Integer(3));
    ....
    SomeClass.doCoolListThings((List) list);

    where doCoolListThings() is a method I get from a third-party
    library. It could merrily do something like list.add(new CoolThing())
    and I don't see how the compiler could complain about that.

    (is that an upcast? If so, would it get implicitly cast if I wrote
    SomeClass.doCoolListThings(list);
    when doCoolListThings is defined as
    public void doCoolListThings(java.util.List list);
    ?)

    Can someone explain why this generics implementation isn't just as
    horrid as const_cast<> is in C++?

    Cheers
    Bent D
    --
    Bent Dalager - - http://www.pvv.org/~bcd
    powered by emacs
    Bent C Dalager, Oct 1, 2003
    #14
  15. In article <>,
    Tor Iver Wilhelmsen <> wrote:
    > (Bent C Dalager) writes:
    >
    >> List<Integer> list = new List<Integer>();
    >> list.add(new Integer(3));
    >> ...
    >> SomeClass.doCoolListThings((List) list);
    >>
    >> where doCoolListThings() is a method I get from a third-party
    >> library. It could merrily do something like list.add(new CoolThing())
    >> and I don't see how the compiler could complain about that.

    >
    >It can because it sees that you pass a typed List to a method that
    >takes untyped List, and can warn you that bad things *could* happen to
    >it.


    Well, yes, but that wasn't the warning I was looking for :)

    So long as we don't have "const" methods, I will end up getting a load
    of uninteresting warnings when calling library algorithms that I know
    won't mutate my List.

    The kind of warning I was looking for is when I actually try to use
    the List in a way that violates its template parameters, i.e., when I
    call List.add() with an unsuitable parameter type after having casted
    the List. I am not looking for a warning when I cast the List to
    something broader.

    I don't believe the compiler can reliably give me the former and I am
    not sure I want the latter.

    Cheers
    Bent D
    --
    Bent Dalager - - http://www.pvv.org/~bcd
    powered by emacs
    Bent C Dalager, Oct 1, 2003
    #15
  16. (Bent C Dalager) writes:

    > List<Integer> list = new List<Integer>();
    > list.add(new Integer(3));
    > ...
    > SomeClass.doCoolListThings((List) list);
    >
    > where doCoolListThings() is a method I get from a third-party
    > library. It could merrily do something like list.add(new CoolThing())
    > and I don't see how the compiler could complain about that.


    It can because it sees that you pass a typed List to a method that
    takes untyped List, and can warn you that bad things *could* happen to
    it.
    Tor Iver Wilhelmsen, Oct 1, 2003
    #16
  17. Dave Stallard

    Phillip Lord Guest

    >>>>> "Tor" == Tor Iver Wilhelmsen <> writes:

    Tor> (Bent C Dalager) writes:

    >> List<Integer> list = new List<Integer>(); list.add(new
    >> Integer(3)); ... SomeClass.doCoolListThings((List) list);
    >>
    >> where doCoolListThings() is a method I get from a third-party
    >> library. It could merrily do something like list.add(new
    >> CoolThing()) and I don't see how the compiler could complain
    >> about that.


    Tor> It can because it sees that you pass a typed List to a method
    Tor> that takes untyped List, and can warn you that bad things
    Tor> *could* happen to it.


    Yes. But that means every time you want to pass a parametrically typed
    object, to an method taking its erasure (or any other super class of
    the parametrically typed object), you will get a warning.

    As you will want to do this a lot, I suspect, the warning will be
    relatively useless.

    Phil
    Phillip Lord, Oct 1, 2003
    #17
  18. Dave Stallard

    Neal Gafter Guest

    Phillip Lord wrote:
    > While I can see how this would work, I wonder whether what you say is
    > true in general though. For instance.....
    >
    >
    > public void add( List list, Object o )
    > {
    > list.add( o );
    > }
    >
    > will this throw a warning, as it can be called as...


    Yes, it will.

    > List<Frame> list;
    > add( list, new Object() );
    >
    > which causes the same difficulty. The general solution to this is to
    > make the type coercion go only in one direction. So List<Frame> can
    > become List, but it involves cloning, or never allowing you to treat
    > the object as List<Frame> again.


    Right, not without a cast (which will provoke a warning).
    Neal Gafter, Oct 2, 2003
    #18
  19. Dave Stallard

    Chris Uppal Guest

    Neal Gafter wrote:

    > If A is a subclass of B, then both List<A> and List<B> are subtypes of
    > List<? extends B>
    > using the recently introduced "wildcards" notation.


    Is there a formal or informal, but complete, write-up of the *current* state of
    Generics anywhere ?

    I've seen stuff that's a few years old now, but nothing that is both recent and
    complete enough for me to understand the new stuff fully*. E.g. this is the
    first *I*'ve heard of the wildcard notation...

    By "fully" I mean that I'd like to be able to:
    - write Java code that uses the new stuff and understand
    what it means (well, obviously!).
    - understand the mechanisms well enough to see 'gotchas'
    myself rather than be told about them by "experts".
    - understand fully how the resulting code is presented
    to the JVM -- I work mostly at bytecode/JNI level
    so Java itself is rather less than half the story.

    TIA

    -- chris
    Chris Uppal, Oct 2, 2003
    #19
  20. Dave Stallard

    Phillip Lord Guest

    >>>>> "Neal" == Neal Gafter <> writes:

    Neal> Phillip Lord wrote:
    >> While I can see how this would work, I wonder whether what you
    >> say is true in general though. For instance..... public void
    >> add( List list, Object o )


    >> { list.add( o ); }


    >> will this throw a warning, as it can be called as...


    Neal> Yes, it will.

    This is not good. You will need to do this so often that the notion of
    "compile without warning and you'll be safe" is lessened. It will be
    hard to compile without warning.


    Phil
    Phillip Lord, Oct 2, 2003
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Juergen Berchtel
    Replies:
    1
    Views:
    5,990
    John C. Bollinger
    May 20, 2005
  2. Generics and Casting

    , Oct 6, 2005, in forum: Java
    Replies:
    6
    Views:
    3,833
    Oliver Wong
    Oct 7, 2005
  3. Replies:
    4
    Views:
    495
    Oliver Wong
    Aug 1, 2006
  4. Random

    Generics - type casting

    Random, Jun 4, 2007, in forum: ASP .Net
    Replies:
    4
    Views:
    471
    Random
    Jun 4, 2007
  5. Soul
    Replies:
    0
    Views:
    518
Loading...

Share This Page