• Post Reply Bookmark Topic Watch Topic
  • New Topic

Mixing generic and non generic legacy code issue  RSS feed

 
Arun Somasundaram
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I encountered the below mentioned exception when I executed the following code :



Output:

Hi
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at pack1.TestList1.main(TestList1.java:12)


But the following code just works fine when the generic type of the List is <Integer> and produces the below mentioned output



Output :

Hi
52
589.235


It is obvious that the generics is used by the compiler at compile time and not by the JVM to ensure the post Java 5 code works with the Pre Java 5 code. It is also clear that the compiler induces the code for type casting in the list.get() when the list uses generics. Here I would like to know why the TestList1 generates the runtime exception and how the TestList2 runs successfully?
 
salvin francis
Bartender
Posts: 1664
37
Eclipse IDE Google Web Toolkit Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well the exception message beats me too
however, i would consider the method to be like this:



This will not compile at all.

also a note, compiling your code gives a warning:
Note: TestList1.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
 
Arun Somasundaram
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ofcourse if the List parameter in the addObjects() uses the <Integer> generic code then the compiler complains about the error. My doubt is why there is no exception generated at runtime when the List type is <Integer> in the main().
 
D. Ogranos
Ranch Hand
Posts: 214
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I assume that in the second case, the compiler ("knowing" that he has a list of Integers) just creates code that uses the "toString()" method of the objects in the list. So the code will run without problems.

For the first case? Again assuming, the compiler expects String objects, so he doesn't use the toString() method. Then the virtual machine finds that the object type is in fact not String. Integer is not convertible to String so you get the exception.

 
Arun Somasundaram
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I assume that in the second case, the compiler ("knowing" that he has a list of Integers) just creates code that uses the "toString()" method of the objects in the list. So the code will run without problems.

For the first case? Again assuming, the compiler expects String objects, so he doesn't use the toString() method. Then the virtual machine finds that the object type is in fact not String. Integer is not convertible to String so you get the exception.


I am not convinced with the second explanation. Is the above two explanations incorrect? if it is incorrect then what could be the reason for the first case to fail?
 
D. Ogranos
Ranch Hand
Posts: 214
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well you can disassemble the created class and look what happens really (use javap -c <classfile>). For the first example, javac creates the following for me:



And for the second example:


In the second case the compiler creates code that just takes Object elements from the list, and passes them to the PrintStream.println(Object) method (which probably uses the toString() method of the object then). In the first case, the compiler uses the PrintStream.println(String) method, and so tries to make sure it actually has String objects with the checkcast instruction. That check fails of course for the non string objects in the list.
 
Arun Somasundaram
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In the second case the compiler creates code that just takes Object elements from the list, and passes them to the PrintStream.println(Object) method


In the second case why the compiler doesn't tries to make sure it actually has Integer objects with the checkcast instruction since the <Integer> generic type is used.
In the first case why the compiler tries to make sure it actually has String objects with the checkcast instruction. If the compiler does make sure about the type of the objects in the first case it must also make sure about the type of the objects in the second case because in the both the cases the collection uses generic types.

Note:

println(int x); is also available
 
Rob Spoor
Sheriff
Posts: 21135
87
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Arun, please read your private messages and follow the instructions in them.
 
D. Ogranos
Ranch Hand
Posts: 214
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Arun.V.S wrote:In the second case why the compiler doesn't tries to make sure it actually has Integer objects with the checkcast instruction since the <Integer> generic type is used.
In the first case why the compiler tries to make sure it actually has String objects with the checkcast instruction. If the compiler does make sure about the type of the objects in the first case it must also make sure about the type of the objects in the second case because in the both the cases the collection uses generic types.


I can only speculate really I guess the checkcast doesn't have anything to do with the collection here, but rather is there to make sure that println(String) has the right parameter type. println(Object) obviously doesn't require such a type check. Note that generics are a source level concept only. They enable the compiler to spot obvious mistakes like inserting integers into string lists. But on the byte code level there isn't a difference between a generic and non-generic list.
 
Arun Somasundaram
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
D. Ogranos wrote:
They enable the compiler to spot obvious mistakes like inserting integers into string lists. But on the byte code level there isn't a difference between a generic and non-generic list.


I haven't said at byte code level there is a difference between generic and non generic list. It's a very basic thing that the generics are used by the compiler to ensure type safety.I don't suppose you have understood my whole point Can any one else give an explanation for it?
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!