SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
Kalyan avvaru wrote:Thanks Ankit...you are a legend. Now almost things are clear.
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 ?
SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
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...
All code in my posts, unless a source is explicitly mentioned, is my own.
SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
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( "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 )
All code in my posts, unless a source is explicitly mentioned, is my own.
All code in my posts, unless a source is explicitly mentioned, is my own.
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.
SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
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.
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
All code in my posts, unless a source is explicitly mentioned, is my own.
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 "special" handled kind of Object (thinking of pools, initialization possibilities) ...
All code in my posts, unless a source is explicitly mentioned, is my own.
Ruben Soto wrote:I just don't know if its worth digging for it
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.)
SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
I know Life is very Tough...But I AM TOUGHER
SCJP 1.5
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
All code in my posts, unless a source is explicitly mentioned, is my own.
SCJP 5
SCJP 5
All code in my posts, unless a source is explicitly mentioned, is my own.
SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
SCJP 5
Jesper Young wrote:The ">" stuff in Ruben's post seems to be a bug in the forum software that we're currently looking into.
SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
Jesper Young wrote:The ">" stuff in Ruben's post seems to be a bug in the forum software that we're currently looking into.
"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.
I know Life is very Tough...But I AM TOUGHER
SCJP 1.5
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!!
All code in my posts, unless a source is explicitly mentioned, is my own.
Jesper Young wrote:The ">" stuff in Ruben's post seems to be a bug in the forum software that we're currently looking into.
All code in my posts, unless a source is explicitly mentioned, is my own.
Ankit Garg wrote:Ruben can you please edit your post and correct the code in it. The code is all messed up
All code in my posts, unless a source is explicitly mentioned, is my own.
SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
All code in my posts, unless a source is explicitly mentioned, is my own.
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.
I know Life is very Tough...But I AM TOUGHER
SCJP 1.5
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.
SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
That feels good. Thanks. Here's a tiny ad:
Smokeless wood heat with a rocket mass heater
https://woodheat.net
|