Win a copy of Mastering Corda: Blockchain for Java Developers this week in the Cloud/Virtualization forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Bear Bibeault
  • Liutauras Vilda
Sheriffs:
  • Jeanne Boyarsky
  • Tim Cooke
  • Junilu Lacar
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Stephan van Hulst
  • Jj Roberts
  • Carey Brown
Bartenders:
  • salvin francis
  • Frits Walraven
  • Piet Souris

List with Unicorn type but you can add a Dragon type?

 
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,

I'm busy with the OCP certification and here I have an example of code:


This gives an ClassCastException, ok that can I understand. But I expect nt compile error at tjhe line "unicorn.add(new Dragon());" , because the list has the type "Unicorn" and you add an Dragon object? Or at least I should expect an runtime error at this line.

What do I not understand or what have I missed?

Nico
 
Saloon Keeper
Posts: 12606
273
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Java discards generic type arguments during compilation. At runtime, every List acts like a List<Object>. This is called type erasure.

On line 3, unicorns is declared as a List<Unicorn>. This is a hint to the compiler that you may only add Unicorn to the list, and not Dragon. If you tried to add a new Dragon to your list in the main() method, the compiler would print an error message.

On line 7, the list is declared as a raw List. Since the variable doesn't use any type bounds, the compiler doesn't perform any type checking for you inside the addUnicorn() method. At runtime line 8 also executes just fine because as I've mentioned above, at runtime every List acts like a List<Object> due to type erasure.
 
Marshal
Posts: 71655
312
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:. . . the compiler doesn't perform any type checking . . .

It should however issue a warning about the use of a raw type. When you return to the calling method and the get() call executes, the runtime performs an implicit cast to (Unicorn) and that cast fails with the exception you mentioned.

By the way: please always say where such code comes from.
 
Saloon Keeper
Posts: 6796
161
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:Java discards generic type arguments during compilation. At runtime, every List acts like a List<Object>. This is called type erasure.


Interestingly, it's not discarded entirely. Consider the following code:


then the output of javap -p LegacyUnicorn.class is



So in some places the type information is preserved. Not for local variables inside of a method, though, so in the case discussed above the JVM couldn't check it at runtime.
 
Stephan van Hulst
Saloon Keeper
Posts: 12606
273
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The compiler preserves the types so that it can perform type checking between different compilation units.

Maybe instead of saying that type arguments are discarded during compilation, I should have said that type arguments are not used at runtime.
 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic