Win a copy of Programmer's Guide to Java SE 8 Oracle Certified Associate (OCA) this week in the OCAJP forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

generics and class literals

 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
How do I call the method

public static void foo(Class<? extends List<? extends CharSequence>> clazz)

using a class literal? Neither of the following lines compiles:

foo(List<String>.class);
foo(List.class);
foo((Class<List<String>> List.class);
 
Anonymous
Ranch Hand
Posts: 18944
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Ilja,

There is no way of doing that with generics due to type erasure. When parametrized types are compiled, the compiler translates these types into bytecode.

See this article on type erasure for more details.

Cheers
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
foo((Class) List.class);

This gives me a warning in my IDE (IntelliJ), but it does compile and run correctly. And the warnings can be dealt with by judicious use of @SuppressWarnings. This is a case where erasure can be made to work for you.

This example would suggest that it was a mistake to give the foo() method such a specific signature - though it's hard to tell exactly at what point did it become too complex. Seems like there's an extra layer of unanticipated complications the moment generic types are nested - i.e. angle braces within angle braces. That may not be a well-justified formal rule, but so far it seems like a good guideline to me: avoid nesting angle braces in generic types. Unless you really need them...
[ May 03, 2006: Message edited by: Jim Yingst ]
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24212
35
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wow!

OK, can you now explain why this works?
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oops! Revisiting this, it looks like I screwed up and found a solution to a modified version of the problem. This doesn't work for the original problem. Nevermind.

Will have to see if there is any other way to do this. Looks doubtful though...
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, here are two solutions, though I imagine neither is really what was desired:

or

Of course the latter is more useful if you want to be able to do anything with the Class parameter wiithin foo().
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ah, solution came to me over lunch.:

The (Object) gets the compiler to ignore what it thinks it knows about the type at compile time, then let you fib about what type it is with a much more specific cast. At run time, it's equivalent to the erasure:

Of course the (Object) cast may be dropped by now. (Probably already was.)

Moral: Food good. Eat more.
[ May 03, 2006: Message edited by: Jim Yingst ]
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jim Yingst:
Ah, solution came to me over lunch.:



Ouch. I don't think we want to use that...

My coworkers have found another solution: subclassing. If you have a class

class StringList extends ArrayList<String>

StringList.class works like a charm. (Our actual code was a little bit more complex, so subclassing proved to simplify the code, anyway.)

Moral: Food good. Eat more.


You're ruining my diet plan!
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jim Yingst:
That may not be a well-justified formal rule, but so far it seems like a good guideline to me: avoid nesting angle braces in generic types. Unless you really need them...


They are certainly not unproblematic, but you can also do very cool things with it.
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jim Yingst:
Ah, solution came to me over lunch.:



We just found out that it suffices to cast to a raw Class:

foo((Class<? extends List<? extends CharSequence>> (Class) List.class);

Makes *kind* of sense, I guess...
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic