Ich versuche, ein Objekt aus einer ArrayList zu entfernen, aber ich erhalte immer einen IndexOutOfBounds Error. Nun gibt es viele Informationen darüber, warum dies passiert, wenn über die ArrayList beim Entfernen iteriert wird, aber das mache ich nicht. Beispiel:
%Vor% druckt [A, B, C]
und schlägt dann mit:
Warum passiert das?
EDIT zur Klärung dieser Frage ist kein Duplikat von diese Frage :
Das spezifische Problem, das hier auftritt, hat nichts mit den üblichen Problemen zu tun, wenn Elemente beim Iterieren entfernt werden. Es wird eher durch die überladene Methode ArrayList remove
und die automatische Typkonvertierung von char
nach int
von java verursacht.
Dieser Aspekt wird in der Antwort auf die andere Frage nicht behandelt.
Es gibt 2 überladene remove
Methoden - eine, die ein int
als Index verwendet und Eine, die ein Object
übernimmt, um die Objektreferenz selbst zu entfernen.
Abschnitt 15.12.2 der JLS behandelt, wie Java eine Überladung einer Methode gegenüber einer anderen auswählt.
Die Phasen sind:
- Die erste Phase (§15.12.2.2) führt die Überladungsauflösung durch, ohne die Boxing- oder Unboxing-Konvertierung zu erlauben oder die Verwendung des Aufrufs der variablen Arity-Methode. Wenn während dieser Phase keine geeignete Methode gefunden wird, wird die Verarbeitung in der zweiten Phase fortgesetzt.
Dies garantiert, dass alle Aufrufe, die in der Java-Programmiersprache vor Java SE 5.0 gültig waren, nicht als mehrdeutig angesehen werden, als Folge der Einführung von Variablenaritätsmethoden, implizitem Boxen und / oder Unboxing. Die Deklaration einer Variablenaritätsmethode (§8.4.1) kann jedoch die für einen bestimmten Methodenmethodenaufrufausdruck gewählte Methode ändern, da eine variable Aritätsmethode in der ersten Phase als feste Methode behandelt wird. Wenn beispielsweise m (Object ...) in einer Klasse deklariert wird, die bereits m (Object) deklariert, wird m (Object) für einige Aufrufausdrücke (wie m (null)) nicht mehr als m (Object []) ausgewählt. ) ist spezifischer.
- Die zweite Phase (§15.12.2.3) führt die Überladungsauflösung durch, während Boxen und Unboxing zugelassen werden , schließt jedoch die Verwendung des Aufrufs der variablen Arity-Methode aus. Wenn während dieser Phase keine geeignete Methode gefunden wird, wird die Verarbeitung in der dritten Phase fortgesetzt.
Dies stellt sicher, dass eine Methode niemals über den Aufruf der Variablenaritätsmethode ausgewählt wird, wenn sie durch den Aufruf der Methode mit fester Arithmetik anwendbar ist.
- Die dritte Phase (§15.12.2.4) erlaubt das Überladen mit variablen Arity-Methoden, Boxing und Unboxing zu kombinieren.
(Hervorhebung meiner)
Beide Methoden sind hier anwendbar, weil ein char
zu einem int
hochgestuft werden kann, aber es kann auch in einen Character
eingereiht werden, der dem Typ-Parameter von a
entspricht. Aber Java wählt die Promotion alleine vor jeder Methode, die Boxen erfordert, also wird 'A'
auf int
hochgestuft, daher der Wert 65.
Sie können es explizit in Character
umwandeln, wenn Sie nach Objektreferenz entfernen möchten.
Die Klasse ArrayList
hat zwei Überladungen der Methode remove
. Eine mit einem Integer-Parameter, die das Element an diesem Index entfernt, und eine mit einem Object
-Parameter.
Sie übergeben ein char
. Dies ist weder ein int
noch ein Object
. Also muss der Compiler entscheiden, welches remove
er verwendet: Fördert er das char
zu einem int
oder boxt es in ein Character
, das dann zu Object
hochgestuft wird.
Die Überladungsauflösung in Java beginnt immer ohne Berücksichtigung von Boxen und Unboxing. Daher wird der remove(int)
Überlastung Priorität eingeräumt. Also nimmt es den Wert des Zeichens A
, was 65 ist, und fördert es nach int, was bedeutet, dass es versuchen wird, das Objekt # 65 zu entfernen, wenn die Liste nur drei Elemente hat.
Um dies zu lösen, müssen Sie es explizit anweisen, ein Character
-Objekt zu verwenden, wie in: remove(Character.valueOf('A'))
.
erwartet, eine Ganzzahl für den Index des zu entfernenden Elements zu erhalten. 'A' gibt den ASCII-Wert von A zurück, der 64 ist und somit außerhalb der Grenzen des Arrays liegt