This week's book giveaway is in the Servlets forum.
We're giving away four copies of Murach's Java Servlets and JSP and have Joel Murach on-line!
See this thread for details.
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Generics - need help Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Generics - need help" Watch "Generics - need help" New topic
Author

Generics - need help

Vinitha Palani
Greenhorn

Joined: Apr 17, 2009
Posts: 10
Hi ranchers

I was trying to see how generics works ..

I have few doubts with regards to the code given below...please help me clear them..



Output:

Me
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
myself
and


1)When a copy of 'li' is passed to the parameter 'list' in addstuff() ,wont 'list' also become type-safe.?
Apparently, it isnt - so what is the reason -type erasure?? ...please could you explain ...

2)What is actually happening in the 'foreach'...?
where is the casting from Integer to String taking place....wont the elements in 'li' be assigned to Object o ,iteratively?


Thanks,
Vinitha
Dwijen Bhattacharjee
Greenhorn

Joined: Mar 31, 2008
Posts: 26
As per my knowledge I am trying to explain your doubt
Type erasure is only for compile time checking. It doesn't exist at runtime. In your code if you change the signature
public void addstuff(List<String> list) then list.add(43); will cause a compile time error. at that time you are not able to add integer in the list whose type is String.

When you are passing a generic list to a non generic method all the security will vanish there. You can add anything in that list.


I copy pasted your code and it executing fine. Not throwing any exception whatever you mentioned. So please execute your code once again.

Sagar Rohankar
Ranch Hand

Joined: Feb 19, 2008
Posts: 2902
    
    1

The magic is in "reference" type and the "object" its pointing.
Vinitha Palani wrote:
1)When a copy of 'li' is passed to the parameter 'list' in addstuff() ,wont 'list' also become type-safe.?
Apparently, it isnt - so what is the reason -type erasure?? ...please could you explain ...
2)What is actually happening in the 'foreach'...?
where is the casting from Integer to String taking place....wont the elements in 'li' be assigned to Object o ,iteratively?

(1)At compile time, In method 'addstuff()', the parameter define is simple 'List list', which is capable of accepting any object. That's why one can add '43' in it, (2) but while executing the code (during run time) in the for each loop, JVM finds object as a primitive int, where as its expect its as a String, that's why it throws an exception.

HTH


[LEARNING bLOG] | [Freelance Web Designer] | [and "Rohan" is part of my surname]
Vinitha Palani
Greenhorn

Joined: Apr 17, 2009
Posts: 10
Hi Dwijen

Thanks!

"When you are passing a generic list to a non generic method all the security will vanish there. You can add anything in that list." - OK ....this answers the first question..

but i am still geting the exception ...did you change anything?

Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9291
    
  17

Vinitha Palani wrote:
but i am still geting the exception ...did you change anything?


The question is, did you use any IDE or something for this code?? There was a long discussion on this about when the compiler inserts a type cast for a generic element. I'll try to search it and provide it...
Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9291
    
  17

I found the thread. Here you can find a good discussion of the problem that you are facing...
Vinitha Palani
Greenhorn

Joined: Apr 17, 2009
Posts: 10
Hi Sagar,

Thanks for the reply.
But the "int" will get Autoboxed wont it?
I tried changing it to Integer -




But the output is still -

In the listMe
In the listmyself
In the listand
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at myfirstapplication.MyClass.main(MyClass.java:14)
Java Result: 1
BUILD SUCCESSFUL (total time: 2 se


Cheers
Vinitha
Vinitha Palani
Greenhorn

Joined: Apr 17, 2009
Posts: 10
yes,i used NetBeans IDE 6.5.1..

Ankit,
Thanks for the link..i will go through it....
Albert Kam
Ranch Hand

Joined: Oct 18, 2007
Posts: 58
Hello,

The response about the runtime type safety is correct according to K&B book.
It's behaviour is like that to enable working together with old legacy code.

About the exception, it does happen, i was surprised too.
I thought Object o in the enhanced for loop will be able to handle it. Well if it's String s that's in the loop, that's another story, hee hee

Anyway, i assume the exception occurs because the reference li is checked for type safety because it's declared with generics type safety. I thought it is only helping in validate what we add into .. not what we get from ..

And thanks for bringing this topic up, as i'm just into the generics chapter here !

(Going for the discussion thread recommended by previous post ..)

Regards,
Albert Kam


Be nice !
Sagar Rohankar
Ranch Hand

Joined: Feb 19, 2008
Posts: 2902
    
    1

Dwijen Bhattacharjee wrote:
When you are passing a generic list to a non generic method all the security will vanish there. You can add anything in that list.

This is the one of the drawbacks of new feature, Generics in Java 5, suppose you have an API which is built as per Java 1.4 spec, and it contains the methods, same as the original example,


Dangerous.
Sagar Rohankar
Ranch Hand

Joined: Feb 19, 2008
Posts: 2902
    
    1

Vinitha Palani wrote:
But the "int" will get Autoboxed wont it?

Yes, it gets "autoboxed" to new Integer(43).
But the thing is, when you say, 'List list', its something like defining, 'List <Object> list', and you know every class in Java is derived from 'Object', so no matter whether you insert int, Integer, Double, OR MyDumbClass's object, its gonna complains at run time, when he dosen't found what he expected (Strings)


Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9291
    
  17

Sagar Rohankar wrote: when you say, 'List list', its something like defining, 'List <Object> list',


Well this is a minute detail but this is not true. You can do this



but you can't do this



I know this is about assignment to the list and what you said applies to adding elements to the list, but I couldn't stop myself from pointing this out as I don't want anyone to have confusions or misconceptions. Actually List list is equivalent to List<? extends Object>...
Sagar Rohankar
Ranch Hand

Joined: Feb 19, 2008
Posts: 2902
    
    1

Ankit Garg wrote:
Sagar Rohankar wrote: when you say, 'List list', its something like defining, 'List <Object> list',


Well this is a minute detail but this is not true. You can do this



but you can't do this



Agreed, but I'm talking in context with the actual code, which takes List as a parameter.

Ankit Garg wrote:
.. but I couldn't stop myself from pointing this out as I don't want anyone to have confusions or misconceptions. Actually List list is equivalent to List<? extends Object>...

Yeah, thanks for the more technical explanation, its "bounded wildcard parametrized types"(If I remeber correctly ). But a little doubt, what is the difference between List<Object> and List<? extends Object>
Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9291
    
  17

Sagar Rohankar wrote:what is the difference between List<Object> and List<? extends Object>


The difference is obvious.

Chaitanya Jadhav
Ranch Hand

Joined: Mar 13, 2009
Posts: 41
* Both object reference variable are refer to only one object :

The type safe reference variable in main method is temporary hold(or use any other word)
when you call add stuff() method,

but variable "list" is not type safe.

* if you modify code exception will not come.


Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9291
    
  17

Chaitanya did you try your code?? The exception doesn't come when you add the element. The exception comes while iterating the List...
Sagar Rohankar
Ranch Hand

Joined: Feb 19, 2008
Posts: 2902
    
    1

@Ankit

Not allowed you to add objects.
whereas, this declaration works smoothly,

The question is, why such behavior ?
Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9291
    
  17

Well I think here you'll get a compile time warning



Now after this warning, if any exception comes in your code, then you are responsible for it. So if you write



then you can't blame the compiler that it didn't complain that something like this could happen.

But when you write



Here you won't get any warnings. So it is the responsibility of the compiler to make sure, that no ClassCastException occurs at runtime. That's why it disallows you to add elements to it. Taking this same example, here, The actual type of the ArrayList is String, but we are using it with a reference of type ? extends Object, so that means that we can try to add Integer to it as Integer is a subtype of Object. But with the ?, it means that the actual type is not known, so it is not sure that it is Integer or String. That's why it disallows you to add anything to the list...
Chaitanya Jadhav
Ranch Hand

Joined: Mar 13, 2009
Posts: 41
Ankit Garg wrote:Chaitanya did you try your code?? The exception doesn't come when you add the element. The exception comes while iterating the List...


Hi Ankit
See the full modified code.
If you modified the code it will run fine. but i don't known whats gotcha.



Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9291
    
  17

This is the gotcha my boy



Just go through the thread that I gave the link to for clarification...
Sagar Rohankar
Ranch Hand

Joined: Feb 19, 2008
Posts: 2902
    
    1

Ankit Garg wrote:

Here you won't get any warnings. So it is the responsibility of the compiler to make sure, that no ClassCastException occurs at runtime. That's why it disallows you to add elements to it.

So whats the use of such declaration, Whats the use any facility which we can't use. Just to avoid compile time warnings ?, which, an average programmer with knowledge of Java generics, can possibly avoid them.
Ankit Garg wrote:
Taking this same example, here, The actual type of the ArrayList is String, but we are using it with a reference of type ? extends Object,

If that's so, then why this code works, the List#add() methods works here.

Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9291
    
  17

Sagar Rohankar wrote:
Ankit Garg wrote:
Taking this same example, here, The actual type of the ArrayList is String, but we are using it with a reference of type ? extends Object,

If that's so, then why this code works, the List#add() methods works here.



Yes its my fault. List is not equivalent to List<? extends Object>. Actually there is no direct way of representing an untyped List using generics.

Sagar Rohankar wrote:
Ankit Garg wrote:

Here you won't get any warnings. So it is the responsibility of the compiler to make sure, that no ClassCastException occurs at runtime. That's why it disallows you to add elements to it.

So whats the use of such declaration, Whats the use any facility which we can't use. Just to avoid compile time warnings ?, which, an average programmer with knowledge of Java generics, can possibly avoid them.


Well the use is to retrieve elements. Suppose you want to create a method that will accept a List of Serializables and serialize the objects, then you can do this

Sagar Rohankar
Ranch Hand

Joined: Feb 19, 2008
Posts: 2902
    
    1

Ankit Garg wrote:Actually there is no direct way of representing an untyped List using generics.


Ankit Garg wrote:
Well the use is to retrieve elements. Suppose you want to create a method that will accept a List of Serializables and serialize the objects, then you can do this

And you get it right, Thanks buddy to making it clear for me I need to dive deep into Generics
Ruben Soto
Ranch Hand

Joined: Dec 16, 2008
Posts: 1032
Ankit Garg wrote:I found the thread. Here you can find a good discussion of the problem that you are facing...

Ankit, do you know why there is an exception in this specific case? It looks as if it might be a detail related to the for-each loop implementation. Simply assigning to an Object variable doesn't do the trick.



All code in my posts, unless a source is explicitly mentioned, is my own.
Vinitha Palani
Greenhorn

Joined: Apr 17, 2009
Posts: 10
Hello Everyone

I ran few test programs to get clarity on this one..i am sharing them ,and summarizing my understanding and what people found out so far,for the purpose of learners like me.

Please correct me if i am wrong -

1.




Output :

run:
Me
myself
and
43
BUILD SUCCESSFUL (total time: 1


2.



Output :
run:
43
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at myfirstapplication.MyClass.main(MyClass.java:14)
Java Result: 1
BUILD SUCCESSFUL (total time: 3 seco


3.To further substantiate this -



Compiler throws an error saying "Incompatible types found:java.lang.Integer required:java.lang.String".

4.


Output:
run:
Me
myself
and
43
BUILD SUCCESSFUL (total time: 2 seconds)

5.

Output :
run:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
Me
at myfirstapplication.MyClass.main(MyClass.java:16)
myself
and
Java Result: 1
BUILD SUCCESSFUL (total time: 2 seconds)



To summarize -
The foreach loop is designed with "generics" and type safety in mind.
When we declare
List<String> li =new ArrayList<String>();
'li' is supposed to hold ONLY string .
But when we give a copy of 'li' to 'list' which is not type-safe,the whole 'generics-assures-type-safety' thing
goes awry.
But ,when we iterate the list ,which is supposed to contain elements of type String ONLY ,using a 'for..each' ,
it expects to find elements which of type String ONLY.


Cheers,
Vinitha





Vinitha Palani
Greenhorn

Joined: Apr 17, 2009
Posts: 10
hey everyone

I am rephrasing the last line in the previous post -

But ,when we iterate the list ,which is supposed to contain elements of type String ONLY ,using a 'for..each' ,
The 'for...each' expects to find elements of type String ONLY.


thanks,
Vinitha

Vinitha Palani
Greenhorn

Joined: Apr 17, 2009
Posts: 10
an interesting finding and ofcourse , few questions

This doesnt give compliler error
List list =new ArrayList<String>();
list.add("Me");
list.add("myself");
list.add("and");
list.add(new Integer(43));


But this does

List<String> list =new ArrayList();
list.add("Me");
list.add("myself");
list.add("and");
list.add(new Integer(43));



So does this means that type safety is decided by the reference variable ..
then why do we declare like this
List<String> list =new ArrayList<String>();

wouldnt this be enuf ??
List<String> list =new ArrayList();

Cheers
Vinitha



Peter Murach
Greenhorn

Joined: Feb 08, 2009
Posts: 5
Hi all,

I would like to add my penny to the discussion. This is my first post so be gentle.

is simply syntacticly equal to


Because 'li' is of List<String> reference type when passed to the addStuff method it is erased of its own type safety so we can add then anything to it. We also need to note that we pass by value, so when the method addStuff finishes, 'li' contains all the four elements and in main method still refers to the same List<String> type which is passed to the expression part of the foreach statement. 'li' returns Iterator<String> in our foreach loop and casts every element to String as shown above. Of course the cast of Integer type will throw runtime exception.

The important thing is not to stop questioning.

Albert Einstein
Vinitha Palani
Greenhorn

Joined: Apr 17, 2009
Posts: 10
Peter,
You hit the nail on the head..!
Thanks.

Any answers for the questions in my last post..?
kalpita lawande
Greenhorn

Joined: Apr 21, 2009
Posts: 9
I am kalpita lawande.I am planning to give scjp 1.5 in june 2009.
can you please tell me which chapters are important and how many mock exams should i give?
Sagar Rohankar
Ranch Hand

Joined: Feb 19, 2008
Posts: 2902
    
    1

Vinitha Palani wrote:
Any answers for the questions in my last post..?

Just look out the discussion between me and Ankit regrading this. Still, here are my short notes on this,
List list =new ArrayList<String>();
consider this statement as,
List<Object> list =new ArrayList<String>();
and you know this is NOT valid, Now one important point to remember, this is for sake of understand, I didn't found any doc/guide which adhere or support this my assumption.

Now, second thing, is little tricky,
List<String> list =new ArrayList();
compiler saw it as,
List<String> list =new ArrayList<Object>();//unchecked warnings.
It throws error, when other than string object is added into it.
because, the method calls are depends upon the reference type, and when compiler saw the reference is of typeList<String>, it invokes the method from List interface as, List#add(String s);, and you see, '43' in not a string.

Vinitha Palani wrote:
So does this means that type safety is decided by the reference variable ..

You can say that, but have you noticed one thing, when you do that, compiler issues warning, but in this case it won't
List<String> list =new ArrayList<String>();

And to explain this point from the master in Generics, check out this link, it clears all the doubts about this point and all the other related to generics.

HTH

Sagar Rohankar
Ranch Hand

Joined: Feb 19, 2008
Posts: 2902
    
    1

kalpita lawande wrote:I am kalpita lawande.I am planning to give scjp 1.5 in june 2009.
can you please tell me which chapters are important and how many mock exams should i give?

Its better to create a new thread for your doubts, rather hijacking others thread, anyways, scroll through this SCJP FAQ, it answers most of your doubt.

And welcome to JR and Best Luck
Dwijen Bhattacharjee
Greenhorn

Joined: Mar 31, 2008
Posts: 26
Now I have a doubt --
whatever the code Vinitha posted at the beginning I simply copy pasted the same code in eclipse and it's generating the output-
Me
myself
and
43

the same code If i compile and run from command line its generating the output--
Me
myself
and
Exception in thread main java.lang.ClassCastException:java.lang.Integer

Both using jdk1.5.0_09.If The problem is with the for..each loop . Then why its generating two different output?
First I thought may be problem with my configuration . But then i thought if both the version is 1.5 then it should present the same output in all the places. Please clarify the doubt.
Vijitha Kumara
Bartender

Joined: Mar 24, 2008
Posts: 3816

Sagar Rohankar wrote:
List list =new ArrayList<String>();
From Java 5, consider this statement as,
List<Object> list =new ArrayList<String>();
and you know this is valid, Now one important point to remember, this is for sake of understand, I didn't found any doc/guide which adhere or support this my assumption.


Again this might be miss-leading someone as List<Object> list =new ArrayList<String>() is not allowed since that will not compile. List<Object> means list of Object's (not any object which is an Object).


SCJP 5 | SCWCD 5
[How to ask questions] [Twitter]
Sagar Rohankar
Ranch Hand

Joined: Feb 19, 2008
Posts: 2902
    
    1

Vijitha Kumara wrote:Again this might be miss-leading someone as List<Object> list =new ArrayList<String>() is not allowed since that will not compile.

Oops, I modified my previous post, But whenever I found this, List list; I conclude it as List<Object> list;. Is it OK ?
Vijitha Kumara
Bartender

Joined: Mar 24, 2008
Posts: 3816

When you say List list it's raw type, it's allowed in order to support legacy code (since in JDK5 List is parameterized). As I said before List<Object> means list of type Object's.
Ruben Soto
Ranch Hand

Joined: Dec 16, 2008
Posts: 1032
Dwijen Bhattacharjee wrote:Now I have a doubt --
whatever the code Vinitha posted at the beginning I simply copy pasted the same code in eclipse and it's generating the output-
Me
myself
and
43

the same code If i compile and run from command line its generating the output--
Me
myself
and
Exception in thread main java.lang.ClassCastException:java.lang.Integer

Both using jdk1.5.0_09.If The problem is with the for..each loop . Then why its generating two different output?
First I thought may be problem with my configuration . But then i thought if both the version is 1.5 then it should present the same output in all the places. Please clarify the doubt.

I've said this many times. Do not use Eclipse, its compiler doesn't always produce the same results as javac.
Ruben Soto
Ranch Hand

Joined: Dec 16, 2008
Posts: 1032
Peter Murach wrote:Hi all,

I would like to add my penny to the discussion. This is my first post so be gentle.

is simply syntacticly equal to


Because 'li' is of List<String> reference type when passed to the addStuff method it is erased of its own type safety so we can add then anything to it. We also need to note that we pass by value, so when the method addStuff finishes, 'li' contains all the four elements and in main method still refers to the same List<String> type which is passed to the expression part of the foreach statement. 'li' returns Iterator<String> in our foreach loop and casts every element to String as shown above. Of course the cast of Integer type will throw runtime exception.

That's a very good point, Peter. I hadn't thought about that (we are calling iterator() on a generic collection.)

Thanks,

Ruben
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Generics - need help
 
Similar Threads
Generics..
generics
Generics
Generics
Generics