wood burning stoves 2.0*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Generic type casting Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCM Java EE 6 Enterprise Architect Exam Guide this week in the OCMJEA forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Generic type casting" Watch "Generic type casting" New topic
Author

Generic type casting

Kalyan avvaru
Greenhorn

Joined: Mar 11, 2009
Posts: 24
Can any one explain why the following program is compiling and running with no errors. Ofcourse no one would ever write a program like this...I am trying to infer how 'Type Erasure' works actually.
If its simply a matter of erasing the replacing the generic types with the absolute types...why the following program is compiling and running?

Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9293
    
  17

Hi Kalyan, welcome to javaranch.

I think you need to know a little bit more about type erasure to understand the program. Your program after type erasure will look like this



So basically since you didn't provide any boundaries on T and UU (changed to avoid abbreviation filter), so they will be resolved to Object class. And as far as the conversion is concerned, the compiler will WARN you that the cast may be unsafe



And there will be no exception at runtime, because uu and t are both of type Object, so converting from an Object reference (containing Integer object) to another Object reference will not result in any exception...


SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
Kalyan avvaru
Greenhorn

Joined: Mar 11, 2009
Posts: 24
Great Ankit..Thanks for your help.
Can you explain why the line 26 when uncommented is throwing exception?. When 'uu' has a value why cant it get what class type it is. As you said if the JVM sees the type of 'UU' as Object(after type erasure) and the run time type is Thread...I would expect to print one of them as type. In either case how the value of 2 is justified for the instance variable uu.

Can you guide me to good resource to study more on this(behind the scenes how compiler handles it). Ofcourse this is just out of curiousity and also helps me to answer well to questions in Generics in SCJP 6.

PS: The stack trace is unpredictable..some times at the beginning some times at the end..why is this happenning...?
Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9293
    
  17

Well on statement 26, there's a ClassCastException. Well the reason for it is simple. The compiler tries to convert the Integer object into a Thread object. This statement

System.out.println( "u of Type UU "+box.uu );

after compilation will become

System.out.println( "u of Type UU "+ ((Thread)box.uu).getClass() );

The cast inserted by the compiler results in the problem...
Kalyan avvaru
Greenhorn

Joined: Mar 11, 2009
Posts: 24
Thanks Ankit...you are a legend. Now almost things are clear.
Kalyan avvaru
Greenhorn

Joined: Mar 11, 2009
Posts: 24
So is it safe to assume...unless a generic type is bounded...compiler 'type erases' generic type to Object, and places type casting when it is accessed ?
Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9293
    
  17

Kalyan avvaru wrote:Thanks Ankit...you are a legend. Now almost things are clear.


I'm not a legend. I'm just a normal boy (yes I'm 20 yrs old) like all of the other people

Kalyan avvaru wrote:So is it safe to assume...unless a generic type is bounded...compiler 'type erases' generic type to Object, and places type casting when it is accessed ?


Yes when a generic type is unbound, then it resolves to Object and compiler puts the type casts wherever necessary...
Ruben Soto
Ranch Hand

Joined: Dec 16, 2008
Posts: 1032
Ankit Garg wrote:Well on statement 26, there's a ClassCastException. Well the reason for it is simple. The compiler tries to convert the Integer object into a Thread object. This statement

System.out.println( "u of Type UU "+box.uu );

after compilation will become

System.out.println( "u of Type UU "+ ((Thread)box.uu).getClass() );

The cast inserted by the compiler results in the problem...

Ankit, do you have any idea why line 24 (System.out.println("u of Type U"+box.u );) is not giving any problems? I would also think a ClassCastException would take place here, but it isn't.


All code in my posts, unless a source is explicitly mentioned, is my own.
Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9293
    
  17

Well for statement 24, the compiler didn't insert any cast. I don't know the exact cases where the compiler inserts a cast but I think since there isn't any method call on uu in statement 24, so the compiler didn't insert any type cast. If you change statement 24 to this

System.out.println( "uu of Type UU "+box.uu.toString() );

Then you'll get a ClassCastException there too. So I feel that the compiler inserts a type cast only when you call a method or do an assignment of the typed field. This is why this statement also results in a ClassCastException (which is pretty obvious)

Thread t = box.uu;

(This UU is killing me )
Sanjay Singhaniya
Greenhorn

Joined: Feb 21, 2009
Posts: 25
I think both of you are legends. Very excellent example.
I think there should be a place in javaranch to list the examples which makes developer think. Any ideas?
Cristian Senchiu
Ranch Hand

Joined: Feb 08, 2009
Posts: 40
I rewrote that piece of code (to make things clearer) into this:


The output will be
  • 1) boxyTwisted1>123<
  • 2) boxyTwisted1>123< [class javaranch.generics.BoxyTwisted1]
  • Exception in thread "main" java.lang.ClassCastException: javaranch.generics.BoxyTwisted1 cannot be cast to javaranch.generics.BoxyTwisted2 at javaranch.generics.BoxTwisted.main(BoxTwisted.java:19)


  • So we see that line 16 doesn't throw but line 18 does.

    # line 16 (makes a default call to the toString()):
    The String concatenations in line 16 are translated into StringBuilder appends by the compiler => ...+box.u is translated to StringBuilder.append(java.lang.Object obj) (Object and not something else, because of the unknown type generic erasure) => following the apis => pseudo code: StringBuilder.append(<String.valueOf(obj)>) => StringBuilder.append(obj.toString())
    So we end up with a call of the toString() on an Object instance => polymorphism => instance of BoxyTwisted1 on the heap => toString() of the BoxyTwisted1. So, no need to cast the instance to anything.

    # line 18 (WE make an explicit call to the toString()):
    The compiler sees here that we make an explicit call to a method of an object which type we declared to be BoxyTwisted2 => it inserts a checkcast instruction in the compiled class. Why this? Because we make an explicit call and we rely on the fact that the instance is of type BoxyTwisted2 (you know, generics -> no need for explicit cast ...).

    I put the method whatAreYou (line 17) there only to tell us what the instance on the heap really is, without throwing.

    The only type of object I know of, for which the javac compiler inserts a checkcast also in the default case (the one as line 16) is String.

    So ... I hope I didn't forget to wrote something ...

    [EDIT1]...[EDIT2]deleted EDIT1 (made a new post)[EDIT3]restored the chars escaped by forum's soft
    Ruben Soto
    Ranch Hand

    Joined: Dec 16, 2008
    Posts: 1032
    Ankit Garg wrote:Well for statement 24, the compiler didn't insert any cast. I don't know the exact cases where the compiler inserts a cast but I think since there isn't any method call on uu in statement 24, so the compiler didn't insert any type cast. If you change statement 24 to this

    System.out.println( &amp;quot;uu of Type UU &amp;quot;+box.uu.toString() );

    Then you'll get a ClassCastException there too. So I feel that the compiler inserts a type cast only when you call a method or do an assignment of the typed field. This is why this statement also results in a ClassCastException (which is pretty obvious)

    Thread t = box.uu;

    (This UU is killing me )

    Thanks Ankit. Well, I think that is really weird, because I think that when you use the string concatenation toString() will get called implicitly on box.u anyway... I am afraid I still don't see the logic to this. I also don't understand why the cast would not be inserted in all situations. I had the idea that the compiler inserted casts always during type erasure.
    Ruben Soto
    Ranch Hand

    Joined: Dec 16, 2008
    Posts: 1032
    Cristian,

    That's an excellent explanation. I think I didn't give enough credit to the compiler for how much care it takes when analyzing the code and performing type erasure. Thanks for putting the time into it.

    Edit: I performed a little modification on your code with (perhaps) surprising results:


    I just replaced String for BoxTwisted2. The reason why I tried doing this is because StringBuilder has an append method that takes a String, and wanted to see if that changed anything. Sure enough, now the compiler casts box.u on the first call.
    Ankit Garg
    Sheriff

    Joined: Aug 03, 2008
    Posts: 9293
        
      17

    Ruben Soto wrote:Thanks Ankit. Well, I think that is really weird, because I think that when you use the string concatenation toString() will get called implicitly on box.u anyway... I am afraid I still don't see the logic to this.


    Well the secret to why toString is not called on box.u lies in the way compiler converts string concatenation. It converts string concatenation into append calls on a StringBuilder object. And StringBuilder class has a append method which takes an object as argument. So a simple statement like this



    will become



    Internally append method will call toString on uu but there will be no type cast there so no ClassCastException
    Cristian Senchiu
    Ranch Hand

    Joined: Feb 08, 2009
    Posts: 40
    Ruben Soto wrote:Cristian,

    That's an excellent explanation. I think I didn't give enough credit to the compiler for how much care it takes when analyzing the code and performing type erasure. Thanks for putting the time into it.

    Edit: I performed a little modification on your code with (perhaps) surprising results:
    ...
    I just replaced String for BoxTwisted2. The reason why I tried doing this is because StringBuilder has an append method that takes a String, and wanted to see if that changed anything. Sure enough, now the compiler casts box.u on the first call.


    Hi Ruben,

    This String behavior is not really surprising... Is the class I wrote about as being an exception, in my initial post, for which the compiler puts checkcast instruction in the .class file. But String being an exception case cannot come from the existence of the String-specialized append() method in the StringBuilder class. StringBuilder has an overloaded append() method also for StringBuffer, yet the following will not make the compiler insert a checkcast in the compiled .class:
    Anyway, String was always a "special" handled kind of Object (thinking of pools, initialization possibilities) ...
    [EDIT]restored the chars escaped by forum's soft
    Ruben Soto
    Ranch Hand

    Joined: Dec 16, 2008
    Posts: 1032
    Ankit Garg wrote:
    Ruben Soto wrote:Thanks Ankit. Well, I think that is really weird, because I think that when you use the string concatenation toString() will get called implicitly on box.u anyway... I am afraid I still don't see the logic to this.


    Well the secret to why toString is not called on box.uu lies in the way compiler converts string concatenation. It converts string concatenation into append calls on a StringBuilder object. And StringBuilder class has a append method which takes an object as argument. So a simple statement like this



    will become



    Internally append method will call toString on uu but there will be no type cast there so no ClassCastException

    Good one, Ankit. Now, let's think about this a little further.

    StringBuilder.append(uu) is getting resolved to which method in StringBuilder? We have two options: append(Object o) and append(String s). In the first case, no class casting will be performed during type erasure. Since that seems to be the case, let's assume it's the method that gets called. Now, append(uu) will perform String.valueOf(uu), which in turn will perform the call uu.toString(). So actually toString() seems to end up being called on uu. Since there is no class casting going on, the call will be performed on uu as an Object reference.

    Maybe the sequence of method calls above is too much for the compiler to check, and that's why the casting on type erasure is not taking place. My guess is that the StringBuilder.append(uu) is inserted at compile time by javac during parsing when it encounters the String concatenation operator, and that's the only thing that the compiler checks. However, notice that if the type of the generic type is a String, the compiler will do the casting (which would make sense, since StringBuilder.append(String s) exists, whereas StringBuilder.append(BoxTwisted1 b) does not.) (EDIT: This theory fails like Cristian pointed out, because it doesn't work for StringBuffer and CharSequence.)

    I think the compiler just looks at explicit method calls in the code after parsing. It looks like it doesn't even bother to see if the method being called is defined in class Object, like it's the case for toString(). If it did, it wouldn't do the casting, since the call would be resolved polymorphically anyway.
    Ruben Soto
    Ranch Hand

    Joined: Dec 16, 2008
    Posts: 1032
    Cristian Senchiu wrote:
    Ruben Soto wrote:Cristian,

    That's an excellent explanation. I think I didn't give enough credit to the compiler for how much care it takes when analyzing the code and performing type erasure. Thanks for putting the time into it.

    Edit: I performed a little modification on your code with (perhaps) surprising results:
    ...
    I just replaced String for BoxTwisted2. The reason why I tried doing this is because StringBuilder has an append method that takes a String, and wanted to see if that changed anything. Sure enough, now the compiler casts box.u on the first call.


    Hi Ruben,

    This String behavior is not really surprising... Is the class I wrote about as being an exception, in my initial post, for which the compiler puts checkcast instruction in the .class file. But String being an exception case cannot come from the existence of the String-specialized append() method in the StringBuilder class. StringBuilder has an overloaded append() method also for StringBuffer, yet the following will not make the compiler insert a checkcast in the compiled .class:
    Anyway, String was always a &quot;special&quot; handled kind of Object (thinking of pools, initialization possibilities) ...

    Hi Cristian,

    You are right. What I meant is that it's surprising that casting is taking place for String and not for other types (including StringBuffer, CharSequence, and BoxTwisted1.) And by surprising I mean unexplained.

    The secret should be in the JLS type erasure specification. I just don't know if its worth digging for it, I'm not sure this is exam material.
    Cristian Senchiu
    Ranch Hand

    Joined: Feb 08, 2009
    Posts: 40
    Ruben Soto wrote:I just don't know if its worth digging for it

    Hi Ruben,
    my thoughts too...
    Ankit Garg
    Sheriff

    Joined: Aug 03, 2008
    Posts: 9293
        
      17

    Ruben Soto wrote:StringBuilder.append(uu) is getting resolved to which method in StringBuilder? We have two options: append(Object o) and append(String s). In the first case, no class casting will be performed during type erasure. Since that seems to be the case, let's assume it's the method that gets called. Now, append(uu) will perform String.valueOf(uu), which in turn will perform the call uu.toString(). So actually toString() seems to end up being called on uu. Since there is no class casting going on, the call will be performed on uu as an Object reference.

    Maybe the sequence of method calls above is too much for the compiler to check, and that's why the casting on type erasure is not taking place. My guess is that the StringBuilder.append(uu) is inserted at compile time by javac during parsing when it encounters the String concatenation operator, and that's the only thing that the compiler checks. However, notice that if the type of the generic type is a String, the compiler will do the casting (which would make sense, since StringBuilder.append(String s) exists, whereas StringBuilder.append(BoxTwisted1 b) does not.)


    First of all Ruben are you confused at this or were you trying to explain a concept.

    Secondly there are many append methods in StringBuffer class one of them takes an Object as argument. Since the type of uu is Thread, and there is no method taking a thread object, so it resolves to the method taking Object argument (as you also pointed out). But generics ends at this point. The call to toString on uu in the append method (or we can say in the String.valueOf() method) will not have any type cast in it. It will only treat uu as an Object reference (as you pointed out again). So basically this is as simple as it can get. It is just like writing this program

    NagarajGoud uppala
    Ranch Hand

    Joined: Nov 13, 2008
    Posts: 86
    Hi,
    ankit at line 24 i am getting copiletime error classcastexceeption while compiling in Jdeveloper IDE.but in command prompt its compiling successfully.why it is behaving like that

    at line 18 when add method called,in the statement this.u = (UU) t;
    'u' is Thread class and 't' is Integer class, there we are trying to convert Integer to Thread class ,in this situation classcastexception must raise,but here not raising why? please explain me.

    Thanks in advance,
    nagaraju.


    I know Life is very Tough...But I AM TOUGHER
    SCJP 1.5
    Cristian Senchiu
    Ranch Hand

    Joined: Feb 08, 2009
    Posts: 40
    Hi nagaraju,

    First problem:
    JDeveloper (as almost any IDE) comes with it's own java compiler, it doesn't use the javac of your installed JDK (this is the one you use when starting compilation from command line). That's why the behavior you observed.
    I used JDeveloper for years and years, before completely moving to Eclipse and NetBeans, and I know that the newer versions have a setting where you can choose javac of your installed JDK. Must be somewhere in project's properties, probably in profiles' compile settings.
    I would say you should change your setting in JDeveloper so that it uses installed JDK to compile, because JDeveloper's compiler has (at least it had as long as I used it) some more (and subtle) compile problems.

    The second problem:
    Type erasure will come to work and erase that UU generic to Object that's why no throwing.
    Ruben Soto
    Ranch Hand

    Joined: Dec 16, 2008
    Posts: 1032
    Ankit Garg wrote:
    First of all Ruben are you confused at this or were you trying to explain a concept.

    Secondly there are many append methods in StringBuffer class one of them takes an Object as argument. Since the type of uu is Thread, and there is no method taking a thread object, so it resolves to the method taking Object argument (as you also pointed out). But generics ends at this point. The call to toString on uu in the append method (or we can say in the String.valueOf() method) will not have any type cast in it. It will only treat uu as an Object reference (as you pointed out again). So basically this is as simple as it can get. It is just like writing this program


    Thanks for taking the time to discuss, Ankit.

    To answer your first question, I was neither trying to prove any point nor confused (although if by not fully understanding you mean confused, then yes, I am confused as I don't understand exactly all the reasons why this is working the way it is.) I was also thinking about the original code and a modified version of the code and maybe I mixed things up a bit.

    Your theory is this: The compiler inserts the StringBuilder.append() method call during parsing, and since there is no StringBuilder.append(Thread t) method, it uses the StringBuilder.append(Object o) method, and thus there is no casting (I agree with this.) The reason why I'm still not convinced that your theory that this is the motivating rule for the casting on type erasure in that case is not taking place is fully correct is the following:



    The code in line // 1 doesn't result in a ClassCastException, even though StringBuilder does have an append(StringBuffer sb) method. Do you see the discrepancy here? If in the case of Thread you justify the fact that the ClassCastException does not take place because StringBuilder.append(Thread t) does not exist, and therefore the call resolves to StringBuilder.append(Object o), then the behavior when you replace Thread with StringBuffer does not fit that theory.

    The JLS type erasure specification looks intimidating, and I'm sure the secret lies there. But, since I'm 100% sure this is not in the exam (according to K&amp;amp;amp;B, the exam doesn't cover the mechanisms that type erasure uses) I will have to pass on this for now. But if you find the solution, please let us know!

    Whenever I edit a post that contains code with characters like " and & it is getting messed up, and it would be too time consuming to fix. Hopefully the software can get fixed (I wonder if anyone noticed this before.) Another annoying thing is the warning you get that tells you not to use abbreviations like "u" which are not proper English, when all you did is use a variable within your code named "u".
    himanshu kesarwani
    Ranch Hand

    Joined: Aug 27, 2008
    Posts: 84
    well done kalyan your question was really very genuine.....even i got confused after seeing your question but ankits answer opened my eyes !!


    SCJP 5
    himanshu kesarwani
    Ranch Hand

    Joined: Aug 27, 2008
    Posts: 84
    wow my all doubts got clear!
    Ruben Soto
    Ranch Hand

    Joined: Dec 16, 2008
    Posts: 1032
    Himanshu,

    Since all your doubts are cleared, would you mind explaining the discrepancy I noted in my previous post? Because I still have that doubt.
    Ankit Garg
    Sheriff

    Joined: Aug 03, 2008
    Posts: 9293
        
      17

    Ruben can you please edit your post and correct the code in it. The code is all messed up
    himanshu kesarwani
    Ranch Hand

    Joined: Aug 27, 2008
    Posts: 84
    Sorry Ruben but i didnt read your post even.........as ankit said you messed up everything !!
    and if you have any more doubts post it in a new forum because this forum is already spoiled by you!!


    Jesper de Jong
    Java Cowboy
    Saloon Keeper

    Joined: Aug 16, 2005
    Posts: 14117
        
      16

    The "&amp;amp;amp;gt;" stuff in Ruben's post seems to be a bug in the forum software that we're currently looking into.


    Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 7 API documentation
    Scala Notes - My blog about Scala
    Ankit Garg
    Sheriff

    Joined: Aug 03, 2008
    Posts: 9293
        
      17

    Jesper Young wrote:The "&amp;amp;amp;amp;gt;" stuff in Ruben's post seems to be a bug in the forum software that we're currently looking into.


    I have also posted this into the ranch office...
    Cristian Senchiu
    Ranch Hand

    Joined: Feb 08, 2009
    Posts: 40
    Jesper Young wrote:The "&amp;amp;amp;amp;gt;" stuff in Ruben's post seems to be a bug in the forum software that we're currently looking into.

    Hi Jesper,
    It happens when one edits a post (two days ago I restored my posts in this thread). The forum's software makes escapes for every special character in the edited message. And if you edit a message more than once .....
    NagarajGoud uppala
    Ranch Hand

    Joined: Nov 13, 2008
    Posts: 86
    "nagaraju wrote(mine)
    at line 18 when add method called,in the statement this.u = (UU) t;
    'u' is Thread class and 't' is Integer class, there we are trying to convert Integer to Thread class ,in this situation classcastexception must raise,but here not raising why?


    "cirstian wrote
    The second problem:
    Type erasure will come to work and erase that UU generic to Object that's why no throwing.


    hi,
    cristian you told that "Type erasure will come to work and erase that UU generic to Object that's why no throwing"
    i didn't understand your answer properly.your saying that is done in compile time, is it?
    but in runtime generics are replaced with original thread,integer type.am i right? so at that time it doesn't convert integer into thread type,it need throw exception.

    my thinking is correct or not?
    please anybody explain me i am confusing

    thanks in advance,
    nagaraju.

    Cristian Senchiu
    Ranch Hand

    Joined: Feb 08, 2009
    Posts: 40
    Hi nagaraju,
    The two generics ( T and UU used in BoxTwisted) are unbounded. That means the compiler will erase both T and UU to java.lang.Object.
    So the method

    will be erased to something like this

    Going further: now the cast is not even needed anymore, as we have Object cast to Object.

    If we go again further (not needed for the SCJP exam, just for fun): in the compiled class, the associated instructions for this method would be something like this:


    P.S.: explanation is based on the code I wrote in my first pot in this thread, that's why the "BoxTwisted" name ...
    Ruben Soto
    Ranch Hand

    Joined: Dec 16, 2008
    Posts: 1032
    himanshu kesarwani wrote:Sorry Ruben but i didnt read your post even.........as ankit said you messed up everything !!
    and if you have any more doubts post it in a new forum because this forum is already spoiled by you!!

    This forum is spoiled by me? I'm discussing exactly what the original post in the thread is all about. You are incredible...
    Ruben Soto
    Ranch Hand

    Joined: Dec 16, 2008
    Posts: 1032
    Jesper Young wrote:The "&amp;amp;amp;amp;gt;" stuff in Ruben's post seems to be a bug in the forum software that we're currently looking into.

    Thank you, Jesper. If I remember correctly that issue not only happens in text within code tags, but also in the main body of the message, when you edit the message and have an ampersand (for example.)
    Ruben Soto
    Ranch Hand

    Joined: Dec 16, 2008
    Posts: 1032
    Ankit Garg wrote:Ruben can you please edit your post and correct the code in it. The code is all messed up

    Ankit, sorry about messing up the code, but I'm afraid I didn't have any control over it. This is a repost and I won't be performing any edits in order to preserve the integrity of the code:
    ******Repost begins
    Thanks for taking the time to discuss, Ankit.

    To answer your first question, I was neither trying to prove any point nor confused (although if by not fully understanding you mean confused, then yes, I am confused as I don't understand exactly all the reasons why this is working the way it is.) I was also thinking about the original code and a modified version of the code and maybe I mixed things up a bit.

    Your theory is this: The compiler inserts the StringBuilder.append() method call during parsing, and since there is no StringBuilder.append(Thread t) method, it uses the StringBuilder.append(Object o) method, and thus there is no casting (I agree with this.) The reason why I'm still not convinced that your theory that this is the motivating rule for the casting on type erasure in that case is not taking place is fully correct is the following:


    The code in line // 1 doesn't result in a ClassCastException, even though StringBuilder does have an append(StringBuffer sb) method. Do you see the discrepancy here? If in the case of Thread you justify the fact that the ClassCastException does not take place because StringBuilder.append(Thread t) does not exist, and therefore the call resolves to StringBuilder.append(Object o), then the behavior when you replace Thread with StringBuffer does not fit that theory.

    The JLS type erasure specification looks intimidating, and I'm sure the secret lies there. But, since I'm 100% sure this is not in the exam (according to K&amp;amp;B, the exam doesn't cover the mechanisms that type erasure uses) I will have to pass on this for now. But if you find the solution, please let us know!
    Ankit Garg
    Sheriff

    Joined: Aug 03, 2008
    Posts: 9293
        
      17

    (I typed a whole long response and it got erased because of the jForum error message )

    Well ruben you are right. Look at this modified code



    The code at line no. 17 will generate an exception. This is the same code that the compiler generates for the println statement. But there is no exception at the println statement. May be this is because the println statement (or infact any string concatenation like at line no 14) is modified to StringBuilder code by the compiler after the generics code is erased...
    Ruben Soto
    Ranch Hand

    Joined: Dec 16, 2008
    Posts: 1032
    Good one, Ankit! Excellent test, which clears up some doubts. Sorry about the JForum issue, it took me a while to clean up the mess that it caused when I edited my message too.
    Cristian Senchiu
    Ranch Hand

    Joined: Feb 08, 2009
    Posts: 40
    Ankit Garg wrote:
    This is the same code that the compiler generates for the println statement. But there is no exception at the println statement. May be this is because the println statement (or infact any string concatenation like at line no 14) is modified to StringBuilder code by the compiler after the generics code is erased...

    Ruben Soto wrote:Good one, Ankit! Excellent test, which clears up some doubts.



    Ankit, Ruben,
    my fellow ranchers, you are going in the wrong direction...
    Is not about the compiler "messing around", one time taking the generics into consideration and one time not. It's about the compiler finding the most specific method (JLS compiler-requirement).
    Let's take those two lines of code which behave different and see what compiler must do for us:



    #lineX
    box.u is the second operand used with a "+" operator, in which the first operand is a String => we are in concatenation case => what rules do we have for concatenation of String with something that is an reference? => two rules: [if reference is null the rule is String+"null"][if reference is a non-null reference the rule is String+<result of calling toString() on the object that reference points to (if null is returned then "null" will be used)>]
    That's all. There's no specific handling for specific types of object, thus no checkcast is needed.

    #lineY
    Here we use box.u as argument of a method. Compiler must look for the most specific method for our argument, finds one and chooses it.
    But then it has to ensure that at runtime the object we give as argument is really of that type. So, in compiled code it inserts a checkcast instruction on that type, in our case checkcast java.lang.StringBuffer. Which of course throws at runtime as the instance on the heap is in fact a BoxyTwisted1.
    If the String

    So, the code at lineX is not the same code the compiler generates for lineY. There's one important difference: lineY makes that checkcast.

    Thus lineY will fail for any type of object that has a specific StringBuilder.append(), including any implementation of CharSequence, java's or ours.
    But it will not fail for other type of objects.

    Let's restore my initial code (so much changed in all these posts ), clean it and add the two lines above plus a dummy implementation of CharSequence:

    Pfui, this was a long one ...

    [edit]:
    This also explains why lineX throws when the type is a String

    as there's the specific concatenation for case String+String and String+<reference> is not the best choice anymore.
    NagarajGoud uppala
    Ranch Hand

    Joined: Nov 13, 2008
    Posts: 86
    Thanks cristian
    now my doubt is cleared. you mean at runtime also the generics will replaced with object type.am i right?
    Ankit Garg
    Sheriff

    Joined: Aug 03, 2008
    Posts: 9293
        
      17

    Maybe Cristian you are right on this front. It might be because of the JLS specification. We were only thinking that the 'box.u' is passed to the append method then there must be a type cast inserted by the compiler. But maybe you are right that this is not about the compiler messing with the code .

    Ruben wrote:Sorry about the JForum issue, it took me a while to clean up the mess that it caused when I edited my message too.


    Ruben you don't need to say sorry again and again. Its not your fault. This problem will be rectified soon...
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: Generic type casting