编辑:我感到非常尴尬。我看错了构造函数。实际被调用的构造函数(如下所示)违反了foreach循环的并发规则,正如Kal的回答所述。
无论如何,非常感谢您的帮助!这仍然会帮助我修复代码中的实际错误。
全部
我是一名相当新的Java程序员,刚开始对该语言有了基本的掌握。我目前正在使用一个对话参与者系统,但首先得尝试将我们系统的逻辑术语表示达到规范要求。我已经快完成了,但遇到了以下错误:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at com.Term.<init>(Term.java:97)
at com.Term.substituteVariables(Term.java:251)
at com.Term.substituteVariables(Term.java:247)
at com.Term.substituteVariables(Term.java:247)
at com.TermPredTestArch.main(TermPredTestArch.java:40)
所涉及的方法 substituteVariables 基本上是一个拷贝构造函数,只不过稍作修改:它接收绑定映射的一个 map,并递归迭代调用它的 Term 对象,沿途查找变量并将其替换为其实例化。令人困惑的是,昨晚我离开时它似乎还能正常工作(尽管我没有进行全面测试),但现在却不听使唤了;我没有做出任何重大修改。
相关代码如下(232-252行):
232 /** Returns a new Term with the appropriate bindings substituted */
233 public Term substituteVariables(Map<Variable, Symbol> bindings) {
234 ArrayList<Symbol> args = this.getArgs();
235 ArrayList<Symbol> newArgs = new ArrayList<Symbol>();
236 Set<Variable> vars = this.getVars();
237 Set<Variable> bindingKeys = bindings.keySet();
238 for(Symbol s: args) {
239 // if s is a Variable, check to see if it has a substituion, and
240 // if so, swap it out
241 if(s instanceof Variable) {
242 if(bindingKeys.contains(s)) newArgs.add(bindings.get(s));
243 else newArgs.add(s);
244 // if s is a Term, add it and recursively substitute any variables
245 // it has within the current set of bindings
246 } else if(s instanceof Term) {
247 newArgs.add(((Term) s).substituteVariables(bindings));
248 // if s is just a symbol, simply add it to the args
249 } else newArgs.add(s);
250 }
251 return new Term(this.getName(), newArgs);
252 }
编辑:这是Term的构造函数:
public Term(String n, ArrayList<Symbol> a) {
super(n);
args = a;
HashSet<Variable> varsToAdd = new HashSet<Variable>();
for(Symbol s: a) parseArg(s.toString());
}
那实际上被调用的构造函数并不是我原以为的那一个。这确实违反了foreach循环的并发规则,正如Kal的回答所述。从我已经做过的研究来看,我知道ConcurrentModificationException通常是由多个线程在没有同步的情况下同时迭代/修改集合引起的,但我这里没有故意的并行性,也没有在类或使用它的测试代码中任何其他地方。否则,我并不完全确定。类的javadoc提到它也可能是由于迭代器同时迭代和修改集合引起的,但我认为我也没有这样做;我只是观察迭代的集合并使用其中的信息来构建另一个集合。这是否也违反了并发规定呢?非常感谢大家能够提供任何指针!我也预先为任何Java礼仪或风格的严重违规道歉(请随时指出!)。谢谢。
Term
的构造函数是什么样子的?这就是异常抛出的地方。 - Jim Garrison