Java无法将子类对象添加到列表中

时间:2013-08-08 22:57:33

标签: java

家长班:

public class Action
    {
        private String eventId;
        private List<ActionArgument> arguments;
        //action to perform when this action is done
        private List<? extends Action> onCompleteActions;

        public Action(){}

        public Action(String eventId, List<ActionArgument> arguments, List<? extends Action> onCompleteActions)
        {
            this.eventId = eventId;
            this.arguments = arguments;
            this.onCompleteActions = onCompleteActions;
        }

        public String getEventId()
        {
            return eventId;
        }
        public void setEventId(String eventId)
        {
            this.eventId = eventId;
        }
        public List<ActionArgument> getArguments()
        {
            return arguments;
        }
        public void setArguments(List<ActionArgument> arguments)
        {
            this.arguments = arguments;
        }
        public List<? extends Action> getOnCompleteActions()
        {
            return onCompleteActions;
        }
        public void setOnCompleteActions(List<? extends Action> onCompleteActions)
        {
            this.onCompleteActions = onCompleteActions;
        }
    }

扩展课程:

public class UserDefinedAction extends Action
{
    // body not important
}

一些服务:

private boolean arrangeBefore(List<? extends Action> defaultActions, UserDefinedAction action)
    {
        String actionToFind = action.getDoBefore();
        boolean actionFound = false;
        for(int i = 0; i < defaultActions.size(); i++)
        {
            if(defaultActions.get(i).getEventId().toUpperCase().equals(actionToFind.toUpperCase()))
            {
                defaultActions.add(i, action);
                return true;
            }
...

所以我在这里有一个错误:defaultActions.add(i, action);说“

add
(int,
capture<? extends com.myPackage.Action>)
in List cannot be applied
to
(int,
com.myPackage.UserDefinedAction)

有人可以向我解释为什么这不起作用吗?

3 个答案:

答案 0 :(得分:1)

一个简单的考虑因素是:

  • 在构造函数中创建输入列表的防御副本。
  • 只需将其存储为列表&lt; Action&gt;。

一般来说,记住 PECS 首字母缩写 - Producer Extends,Consumer Super 是很有用的。如果要使用有界类型变量或通配符向List添加元素,则需要使用super而不是extends来表达它。例如,List&lt;?超级A&gt;表示列表成员类型是A的一些超类

答案 1 :(得分:0)

您不能将任何类型的参数传递给其中带有通配符的方法。在这里,您有一个List<? extends Action>,并且您尝试添加UserDefinedAction

但是Java并不知道List的确切泛型类型;它假设它可以是任何东西,甚至像List<SomeOtherAction>之类的东西。由于这个原因,您无法在列表中添加UserDefinedAction。出于这个原因,Java不允许你调用这样的方法。

要解决此问题,您需要在Action类上定义泛型类型参数:

public class Action<A extends Action>

然后,您可以使用<? extends Action>替换该班级中的所有<E>。这样,Action<Action>就可以处理List<Action>

接下来,将A中的UserDefinedAction定义为UserDefinedAction。这样,UserDefinedAction可以处理List<UserDefinedAction>,这样您就可以add UserDefinedAction

public class UserDefinedAction extends Action<UserDefinedAction>

或者,您可以更灵活地以这种方式定义UserDefinedAction

public class UserDefinedAction<A extends UserDefinedAction> extends Action<A>

...并使用UserDefinedAction<UserDefinedAction>实例。这将允许UserDefinedAction的更多子类以他们想要的方式定义泛型类型参数A

答案 2 :(得分:0)

您可以更改方法的签名并在其中使用泛型:

public <A extends Action> void arrangeBefore(List<A> actionList, A action) {
    actionList.add(action);
}

请注意,此更改假定A actionarrangeBefore使用的方法仅属于Action类。