tags:

views:

84

answers:

3

I am getting this error with the following code:

The method getItemProperty(capture#2-of ? extends GenericTest.Item) in the type GenericTest.BaseContainer<capture#2-of ? extends GenericTest.Item> is not applicable for the arguments (GenericTest.Item)

import org.junit.Test;

public class GenericTest {

public class Item {
    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

public class WordItem extends Item {

}

public abstract class BaseContainer<T extends Item> {
    public String getItemProperty(T item) {
        return item.getValue();
    }
}

public class Document extends BaseContainer<WordItem> {
}

public static class ContainerFactory {
  public static BaseContainer<? extends Item> getContainer(Item item) {
     return new GenericTest().new Document();
  }
}

@Test
public void theTest(){
    Item item = new WordItem();
    BaseContainer<? extends Item> container = ContainerFactory.getContainer(item);
    String str = container.getItemProperty(item); //this line does not compile
}
}

I´m using Eclipse Helios with jdk 1.6.0_16.

+1  A: 

To get rid of the error, change your code to:

public static class ContainerFactory {
  public static <T extends Item>BaseContainer<T> getContainer(Item item) {
     return (BaseContainer<T>) new GenericTest().new Document();
  }
}

@Test
public void theTest(){
    Item item = new WordItem();
    BaseContainer<Item> container = ContainerFactory.getContainer(item);
    String str = container.getItemProperty(item);
}
True Soft
thanks a lot... that worked
Alex
+2  A: 

I think the problem is that container is a BaseContainer<? extends Item>, i.e. it is a container of some subtype of Item. However, the compiler has no way of ensuring that the subtype in question is actually Item itself. And in fact it is WordItem, not Item. The overall problem is that your generic parameter usage is not consistent and full.

I could make your code compile with these modifications:

public class Document<T extends Item> extends BaseContainer<T> {
}

public static class ContainerFactory {
  public static <T extends Item> BaseContainer<T> getContainer(T item) {
     return new Test().new Document<T>();
  }
}

@Test
public void theTest(){
    WordItem item = new WordItem();
    BaseContainer<WordItem> container = ContainerFactory.getContainer(item);
    String str = container.getItemProperty(item);
}

This differs from TrueSoft's suggestion in that here Document is also made generic - this may not be what you want (you gave no info regarding this), but at least this way there is no unsafe cast required within getContainer().

Péter Török
A: 

You could change getItemProperty()'s parameter from T to Item, like this:-

public abstract class BaseContainer<T extends Item> {
    public String getItemProperty(Item item) {
        return item.getValue();
    }
}
limc