我正在尝试从ArrayList中删除一个对象,但我不断收到IndexOutOfBounds错误。现在有足够的信息可以解释为什么在迭代而删除的ArrayList 时会发生这种情况,但是我没有这样做。 例如:
ArrayList<Character> a = new ArrayList<Character>();
a.add('A');
a.add('B');
a.add('C');
System.out.println(a);
a.remove('A');
System.out.println(a);
打印[A, B, C]
,然后以:
java.lang.IndexOutOfBoundsException: Index: 65, Size: 3
at java.util.ArrayList.rangeCheck(ArrayList.java:635)
at java.util.ArrayList.remove(ArrayList.java:474)
at b.<init>(b.java:23)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at bluej.runtime.ExecServer$3.run(ExecServer.java:746)
为什么会这样?
编辑澄清此问题不是this question的重复:
此处发生的具体问题与迭代时删除元素时的常见问题无关。它更多是由重载的ArrayList remove
方法和java从char
到int
的自动类型转换引起的。
另一个问题的答案中没有涉及这方面。
答案 0 :(得分:22)
有2个重载的remove
方法 - one that takes an int
as an index和one that takes an Object
,用于删除对象引用本身。
Section 15.12.2 of the JLS介绍了Java如何选择一种方法重载而不是另一种方法。
阶段是:
- 第一阶段(第15.12.2.2节)执行重载解析而不允许装箱或拆箱转换,或使用变量arity方法调用。如果在此阶段没有找到适用的方法,则处理继续到第二阶段。
醇>这保证了在Java SE 5.0之前在Java编程语言中有效的任何调用都不会因为引入变量arity方法,隐式装箱和/或取消装箱而被认为是不明确的。但是,变量arity方法(第8.4.1节)的声明可以更改为给定方法方法调用表达式选择的方法,因为变量arity方法在第一阶段被视为固定arity方法。例如,在已声明m(Object)的类中声明m(Object ...)会导致不再为某些调用表达式(例如m(null))选择m(Object),因为m(Object [] )更具体。
- 第二阶段(§15.12.2.3)执行重载解析同时允许装箱和拆箱,但仍然排除使用变量arity方法调用。如果在此阶段没有找到适用的方法,则处理继续到第三阶段。
醇>这确保了如果通过固定的arity方法调用适用,则永远不会通过变量arity方法调用选择方法。
- 第三阶段(§15.12.2.4)允许重载与变量arity方法,装箱和拆箱相结合。
醇>
(大胆强调我的)
这两种方法都适用于此,因为可以将char
提升为int
,但也可以将其设置为Character
,匹配a
的类型参数。但是Java会在任何需要装箱的方法之前单独选择促销,因此'A'
会提升为int
,因此值为65。
如果要通过对象引用删除,可以将其显式转换为Character
。
a.remove((Character) 'A');
答案 1 :(得分:4)
remove
方法需要一个索引,它会删除指定索引处的项目。您正在传递一个char,因此它将转换为整数65。
答案 2 :(得分:4)
ArrayList
类有两个方法remove
的重载。一个带有整数参数,用于删除该索引处的项目,另一个带有Object
参数的项目。
您正在传递char
。这既不是int
也不是Object
。因此,编译器必须决定它使用哪个remove
:它是否将char
提升为int
,还是将其加入Character
,然后将其提升为Object
remove(int)
。
Java中的重载解析始终在不考虑装箱和拆箱的情况下启动。因此,它优先考虑A
重载。因此它需要字符Character
的值,即65,并将其提升为int,这意味着当列表只有三个项目时,它将尝试删除项目#65。
要解决此问题,您需要明确告诉它使用remove(Character.valueOf('A'))
对象,如:unsigned int x = 255;
myserial->putChar( static_cast<char>(x) );
。
答案 3 :(得分:2)
应该将索引传递给Arraylist的remove方法。试图替换这一行 a.remove( 'A');与
a.remove(0);
答案 4 :(得分:1)
a.remove()
期望获取要删除的项的索引的整数。 'A'返回A的ASCII值,即64,因此超出了数组的边界