Java ArrayList移除对象-IndexOutOfBoundsException

Java ArrayList移除对象-IndexOutOfBoundsException,java,arraylist,Java,Arraylist,我试图从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');

我试图从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);
为什么会这样

编辑以澄清此问题不是重复的:

这里出现的具体问题与迭代时删除元素时的常见问题无关。这是由重载的ArrayList
remove
方法和java自动将
char
类型转换为
int
引起的


另一个问题的答案中没有涉及这方面。

删除方法需要一个索引,并在指定索引处删除一项。您正在传递一个字符,因此它被转换为一个整数65

a.remove()

期望为要删除的项的索引获取一个整数。'A'返回A的ASCII值,该值为64,因此超出了数组的界限

有2个重载的
remove
方法--,以及,删除对象引用本身

介绍Java如何选择一种方法重载而不是另一种方法重载

这些阶段是:

  • 第一阶段(§15.12.2.2)执行重载解析,不允许装箱或拆箱转换,也不允许使用变量算术方法调用。如果在此阶段没有找到适用的方法,则处理继续到第二阶段
  • 这保证了在Java SE 5.0之前的Java编程语言中有效的任何调用都不会因为引入变量arity方法、隐式装箱和/或取消装箱而被认为是不明确的。然而,变量arity方法的声明(§8.4.1)可能会改变为给定方法调用表达式选择的方法,因为变量arity方法在第一阶段被视为固定arity方法。例如,在已经声明了m(对象)的类中声明m(对象…)会导致不再为某些调用表达式(例如m(null))选择m(对象),因为m(对象[])更具体

  • 第二阶段(§15.12.2.3)执行重载解析,同时允许装箱和拆箱,但仍然禁止使用变量arity方法调用。如果在此阶段没有找到适用的方法,则处理继续到第三阶段
  • 这确保了如果方法通过固定arity方法调用适用,则永远不会通过变量arity方法调用选择该方法

  • 第三阶段(§15.12.2.4)允许重载与可变算术方法、装箱和拆箱相结合
  • (粗体强调)

    这两种方法在这里都适用,因为
    char
    可以提升为
    int
    ,但也可以将其装箱为
    字符
    ,与
    的类型参数匹配。但是Java会在任何需要装箱的方法之前单独选择升级,因此
    'A'
    被升级为
    int
    ,因此值为65

    如果要按对象引用删除,可以将其显式强制转换为
    字符

    a.remove((Character) 'A');
    

    应将索引传递给Arraylist的remove方法。试着换这条线 a、 删除(“a”);与


    a、 移除(0)

    类有两个方法
    remove
    的重载。一个带有整数参数,用于删除该索引处的项,另一个带有
    对象
    参数

    您正在传递一个
    char
    。这既不是
    int
    也不是
    对象
    。因此,编译器必须决定使用哪个
    删除
    :是将
    字符提升为
    int
    ,还是将其装箱为
    字符,然后提升为
    对象

    Java中的重载解析总是在不考虑装箱和取消装箱的情况下启动。因此,它优先考虑
    remove(int)
    重载。因此,它接受字符
    A
    的值,即65,并将其提升为int,这意味着当列表只有三个项目时,它将尝试删除项目#65


    要解决这个问题,您需要明确告诉它使用
    字符
    对象,如:
    remove(Character.valueOf('a'))

    您要使用
    a.remove(0)尝试:
    a.remove((字符)'a')
    我特别想删除一个对象,而不是索引,如本文所述:是的,但是
    'a'
    是一个基本类型,因此
    remove(int-index)
    被用来代替
    remove(object o)
    @Jarrod Roberson您提到的重复问题并没有回答我的问题。我完全了解在迭代和删除元素时可能出现的问题,但是我的问题的答案是,删除方法重载,并且从char到int的类型升级导致失败。实际上,A是65,就像在异常消息中一样。它不是真正的ASCII值,而是UTF-16代码点,恰好与拉丁1值相同,恰好与ASCII值相同。人们说代码点是ASCII值,这有点让我恼火。@DavidConrad我完全同意你的观点,但我想你的意思是说UTF-16代码单元。代码点是绝对的,不是编码。@Klitos谢谢。我确实应该说是代码单元。那会删除
    'B'
    a.remove((Character) 'A');