6

I am trying to extend the following class with constructor (from the Ektorp library):

public class CouchDbRepositorySupport<T extends CouchDbDocument> implements GenericRepository<T> {

...

protected CouchDbRepositorySupport(Class<T> type, CouchDbConnector db) {
...

}

Here's my implementation:

public class OrderRepository extends CouchDbRepositorySupport<Order<MenuItem>> {

    public OrderRepository(CouchDbConnector db) {
        super(Order<MenuItem>.class, db);

The problem is with the Order<MenuItem>.class part. The Java compiler tells me:

 Syntax error on token ">", void expected after this 

I tried with (Order<MenuItem>).class, Order.class and new Order<MenuItem>().getClass() with no better luck.

What can I do to retrieve the .class attribute of a generic class?

jd.
  • 4,057
  • 7
  • 37
  • 45
  • 1
    There seems to be one of these a week. – Paul Bellora May 15 '12 at 20:16
  • 2
    @PaulBellora Possibly because any google query or SO query only returns questions about finding out the type of a generic object at runtime. This problem is somewhat different. – jd. May 15 '12 at 20:36

2 Answers2

2

The correct syntax would be:

Order.class

In Java, Order<MenuItem>.class and Order.class are the same class at runtime, the generic type information (the <MenuItem> type parameter) is lost at runtime because of type erasure - a severe limitation of Java's generic type system.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • The java compiler disagrees with that: `The constructor CouchDbRepositorySupport>(Class, CouchDbConnector) is undefined` – jd. May 15 '12 at 20:13
  • @jdreux you've said it yourself: the _compiler_. Generic types are checked during compilation, whereas the expression `Order.class` is evaluated at runtime, and at runtime the type parameter `` is _erased_ from the type information of the class, as if it never had existed – Óscar López May 15 '12 at 20:18
  • So there is not syntax for Order.class because it's runtime equivalent does not exist? – jd. May 15 '12 at 20:37
  • @jdreux That's right. Read about it in this excellent [FAQ](http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ101), look at the questions "What is type erasure?" and "What is reification?". Quoting: "The JVM cannot tell the difference between a List and a List" – Óscar López May 15 '12 at 20:43
1

If you change your type to publish the inner type, you can get it this way:

public class CouchDbRepositorySupport<C, T extends CouchDbRepositorySupport<C>> implements GenericRepository<T> {
...

    protected CouchDbRepositorySupport(Class<C> type, CouchDbConnector db) {
        ...
    }

public class OrderRepository extends CouchDbRepositorySupport<MenuItem, Order<MenuItem>> {

    public OrderRepository(CouchDbConnector db) {
        super(MenuItem.class, db);

You have a few choices about how you declare the parent class; this is just one example.

Disclaimer: I did this by hand without an IDE, so there could be a few minor syntax issues with it, but the concept should work.

Bohemian
  • 412,405
  • 93
  • 575
  • 722