使用java泛型时如何解决此通配符捕获问题?

时间:2014-12-18 18:27:13

标签: java generics bounded-wildcard

我在使用java泛型时遇到问题 - 特别是使用通配符捕获。这是我所拥有的代码的简化版本,它展示了我所看到的问题。这让我抓狂:

public class Task {

    private Action<ActionResult, ? extends ActionSubject> action;
    private ActionSubject subject = new ActionSubjectImpl();

    private List<ActionResult> list = new ArrayList<>();

    public static void main(String[] args) {
        Task task = new Task();
        task.setAction(new ActionImpl());
        task.doAction();
    }

    public void setAction(Action<ActionResult, ? extends ActionSubject> action) {
    this.action = action;
    }

    public void doAction() {
        list.add(action.act(subject));
    }      

    public static class ActionResult { }

    public interface Action<T, U> {
        public T act(U argument);
    }    

    public interface ActionSubject {
        public String getName();
    }

    public static class ActionImpl implements Action<ActionResult, ActionSubjectImpl>{
        @Override
        public ActionResult act(ActionSubjectImpl argument) {
            // Code that requires ActionSubjectImpl specifically instead of the interface.
            // This classes implmentation of action should only support ActionSubjectImpl as an
            // argument.
            return new ActionResult();
        }
    }

    public class ActionSubjectImpl implements ActionSubject {
        @Override
        public String getName() {
            return "I am a subject";
        }
    }
}

不包括包裹声明和进口 - 否则这是完整的。这不编译。问题出在片段list.add(action.act(subject));,我看到错误消息:

incompatible types: ActionSubject cannot be converted to CAP#1
 where CAP#1 is a fresh type-variable:
  CAP#1 extends ActionSubject from ? extends ActionSubject

我可以从其他帖子中看到辅助方法被建议作为一种方式使这样的事情发挥作用,但我无法想出一个有效的方法。

Action action的类型参数如下:Action<ActionResult, ? extends ActionSubject>和我传递给ActionSubject方法的act是接口类型'ActionSubject'的具体类型'ActionSubjectImpl'虽然有问题的代码片段不会看到具体类型的课程。 Action的第二个类型参数应该支持任何扩展ActionSubject的类型 - 当我将action设置为new ActionImpl()时,它就可以了,其中第二个类型是ActionSubjectImpl }。

对于我在定义和使用泛型中所做错误的任何评论,我将不胜感激。我可能会遗漏一些基本的东西。我可以用不同的方式对此进行编码,但在我明白出现问题之前,我将无法继续前进。

感谢。

1 个答案:

答案 0 :(得分:10)

这是你的误解:你说:

  

Action的第二个类型参数应该支持任何扩展ActionSubject

的类型

这不正确。 Action的第二个类型参数被约束为ActionSubject的特定子类,例如MyActionSubject。因此,您无法传递任意ActionSubject实例,因为这是一种更通用的类型。

如果您想拥有ActionSubject的任意子类型,只需使用ActionSubject作为第二个类型参数,而不是? extends ActionSubject