Java ArrayList Objekt entfernen - IndexOutOfBoundsException

7

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:

fehl %Vor%

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.

    
Stefan 06.01.2016, 21:42
quelle

5 Antworten

20

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:

     
  1. 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.
  2.   

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.

     
  1. 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.
  2.   

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.

     
  1. Die dritte Phase (§15.12.2.4) erlaubt das Überladen mit variablen Arity-Methoden, Boxing und Unboxing zu kombinieren.
  2.   

(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.

%Vor%     
rgettman 06.01.2016, 21:46
quelle
4

Die Methode remove erwartet einen Index und entfernt ein Element am angegebenen Index. Sie übergeben ein Zeichen, daher wird es in eine Ganzzahl 65 umgewandelt.

    
mic4ael 06.01.2016 21:45
quelle
4

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')) .

    
RealSkeptic 06.01.2016 21:57
quelle
2

Sollte den Index an die remove-Methode von Arraylist übergeben. versuchen, diese Zeile zu ersetzen a.entfernt ('A'); mit

a.remove (0);

    
jayachsi 06.01.2016 21:48
quelle
1
%Vor%

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

    
Avi Gurfinkel 06.01.2016 21:45
quelle

Tags und Links