Optaplanner自定义影子变量报错:如何修复通知计数异常问题?
问题修复方案
错误原因分析
你遇到的IllegalStateException是因为VariableListener的实现违反了OptaPlanner的核心规则:
- 错误地针对真实规划变量x调用了
beforeVariableChanged/afterVariableChanged,而非要更新的影子变量y - 方法内引用了未定义的
sourcevariable,应该使用方法传入的variable参数 - 泛型参数和类名不符合Java命名规范(首字母需大写,如
PlanningSolution、Variable)
修正后的VariableListener代码
public class YVariableListener implements VariableListener<PlanningSolution, Variable> { @Override public void beforeEntityAdded(ScoreDirector<PlanningSolution> scoreDirector, Variable variable) { // 初始化影子变量y scoreDirector.beforeVariableChanged(variable, "y"); variable.setY(variable.getX() * 10); scoreDirector.afterVariableChanged(variable, "y"); } @Override public void afterEntityAdded(ScoreDirector<PlanningSolution> scoreDirector, Variable variable) { // 无需额外操作 } @Override public void beforeVariableChanged(ScoreDirector<PlanningSolution> scoreDirector, Variable variable) { // 无需额外操作 } @Override public void afterVariableChanged(ScoreDirector<PlanningSolution> scoreDirector, Variable variable) { // 更新影子变量y scoreDirector.beforeVariableChanged(variable, "y"); variable.setY(variable.getX() * 10); scoreDirector.afterVariableChanged(variable, "y"); } @Override public void beforeEntityRemoved(ScoreDirector<PlanningSolution> scoreDirector, Variable variable) { // 无需额外操作 } @Override public void afterEntityRemoved(ScoreDirector<PlanningSolution> scoreDirector, Variable variable) { // 无需额外操作 } }
关键修正点说明
- 针对影子变量操作:更新影子变量
y时,必须调用scoreDirector.beforeVariableChanged(variable, "y")和scoreDirector.afterVariableChanged(variable, "y"),告知ScoreDirector要修改的是影子变量y,而非真实变量x。 - 初始化影子变量:在
beforeEntityAdded方法中初始化y,确保实体添加时影子变量就有正确值,避免初始分数计算错误。 - 修正变量引用:使用方法传入的
variable参数,替代未定义的sourcevariable。 - 规范命名:泛型参数和类名遵循Java大驼峰命名规范(如
PlanningSolution、Variable、YVariableListener)。
额外检查项
确保在PlanningEntity类中,影子变量y通过@ShadowVariable注解正确关联到真实变量x:
@PlanningEntity public class Variable { @PlanningVariable(...) private Integer x; @ShadowVariable(variableListenerClass = YVariableListener.class, sourceVariableName = "x") private Integer y; // getter和setter方法 public Integer getX() { return x; } public void setX(Integer x) { this.x = x; } public Integer getY() { return y; } public void setY(Integer y) { this.y = y; } }
内容的提问来源于stack exchange,提问作者yassine
相关产品推荐
相关产品推荐

