简体   繁体   中英

Java Generic: Why compiler can not resolve type T to inherited type in method?

I've got classes

public class DiaryItem extends AbstractInfoElement { ... };

public class EventItem extends AbstractInfoElement { ... };

public class StickerItem extends AbstractInfoElement { ... };

public class TodoItem extends AbstractInfoElement { ... };

I've got overridden methods to do something with this parameters:

class DBEngine {

    public long add(EventItem item){ ... };

    public long add(StickerItem item){ ... };

    public long add(TodoItem item){ ... }

}

Then I realized template class to manipulate types in generic way

public class AddItemCommand<T extends AbstractInfoElement>{

    private final T item;

    public AddItemCommand(T item) {
        this.item = item;
    }

    void doSmth() {
      add(item);
    }
}

I suppose compiler resolve T as needed type, but I got issues:

Error:(78, 45) error: no suitable method found for add(T)
method DBEngine.add(DiaryItem) is not applicable
(argument mismatch; T cannot be converted to DiaryItem)
method DBEngine.add(EventItem) is not applicable
(argument mismatch; T cannot be converted to EventItem)
method DBEngine.add(StickerItem) is not applicable
(argument mismatch; T cannot be converted to StickerItem)
method DBEngine.add(TodoItem) is not applicable
(argument mismatch; T cannot be converted to TodoItem)
where T is a type-variable:
T extends AbstractInfoElement declared in class AddItemCommand

My goal was to avoid overcoding in those cases:

AddItemCommand<DiaryItem> cmdDiary = new AddItemCommand<DiaryItem>(new DiaryItem);
cmdDiary.doSmth();

should call

DBEngine.add(DiaryItem item);

and

AddItemCommand<TodoItem> cmdTodo = new AddItemCommand<TodoItem>(new TodoItem);
cmdTodo.doSmth();

should call

DBEngine.add(TodoItem item);

That's all, but doesn't work ... Those issues are at compile time...

BTW... Excuse my poor english

From your error messages it appears that you only have add methods for the concrete subclasses, DiaryItem , EventItem , StickerItem , and TodoItem , but then you attempt to call add with an argument of type T extends AbstractInfoElement .

That does not work as T ("any subclass of AbstractInfoElement") does not match either of the specific subclasses.

Edit: note that Java only does dispatch on static type (ie, which of the overloaded methods to call is selected based on the type known at compile-time), so it has no way of knowing if T matches one of the subclasses.

(see eg, How does Java method dispatch work with Generics and abstract classes? , Java Generic / Type Dispatch Question , Method overloading and generics )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM