ursprüngliche ArrayList ändert sich bei Übergabe in Methode

kuribali

Neues Mitglied
Hallo,
Ich habe ein Problem, das mich jetzt schon seit geraumer Zeit beschäftigt. Wenn ich eine ArrayList an eine Methode übergebe und in der Methode ein Element bearbeite, dann ändert sich auch die ursprüngliche Variable.

Java:
import java.util.ArrayList;

public class Main {

    static ArrayList<Integer> i = new ArrayList<>();

    public static void main(String[] args) {
        i.add(0);

        System.out.println(i.get(0));
        test(i);
        System.out.println(i.get(0));
    }

    private static void test(ArrayList<Integer> i1) {
        i1.set(0, 1);
    }

}

Die erste Ausgabe ist 0, die zweite 1. Bei jedem anderen Datentyp, den ich getestet habe, ließ sich die Variable so nicht ändern.
Ich würde gerne wissen, wodurch das entsteht und noch wichtiger, wie man es umgehen kann.
Danke im Vorraus
 

mrBrown

Super-Moderator
Mitarbeiter
Das passiert in Java bei jedem Objekt, solange das Objekt selbst das nicht verhindert (zB indem es keine Methoden gibt, die das Objekt verändern).

Das liegt daran, dass immer nur eine Referenz auf das Objekt übergeben wird, und in der Methode mit dem selben, nicht nur gleichen, Objekt gearbeitet wird.


In dem ArrayList-Fall müsstest du die Liste zb vorher kopieren, damit in der Methode eine andere genutzt wird.
 

RalleYTN

Bekanntes Mitglied
Java arbeitet mit Call-By-Value.
Wenn du also einen Int übergibst der den Wert 3 hat, dann übergibst du den Wert 3.
Wenn du jetzt Objekte übergibst, dann ist der Wert die Referenz zum Objekt.
Dass heisst, dass das Objekt, welches du übergeben hast, praktisch das Selbe ist.

Wenn du das jetzt unabhängig vom original bearbeiten möchtest musst du zuerst eine Kopie erstellen.
Dafür guckst du dir am besten mal die Methode "clone" an.
 

Neumi5694

Top Contributor
Da du anscheinend in der Methode Elemente hinzufügen oder ersetzen willst, musst du eine Kopie der Liste übergeben oder aber in der Methode eine Kopie erstellen und mit dieser arbeiten.
Wenn es sich bei den einzelnen Elemente um änderbare Objekte handelt, dann wirkt sich eine Änderung der Eigenschaften eines Elements auch nach außen hin aus.
Um DAS zu verhindern, musst du Kopien der einzelnen Elemente anlegen (Stichwort "deepclone").
 

Joah

Mitglied
Bei jedem anderen Datentyp, den ich getestet habe, ließ sich die Variable so nicht ändern.

Doch das was du gemacht hast sollte mit jeder Klasse gehen.
Es geht aber nicht mit z. B. int, weil das zwar ein Datentyp ist, aber keine Klasse.
und ArrayList kannst du nur mit Klassen verwenden.
Hier z. B. mit String:
Java:
import java.util.ArrayList;

public class Main {

    static ArrayList<String> i = new ArrayList<>();

    public static void main(String[] args) {
        i.add("Test 0");

        System.out.println(i.get(0)); // gibt "Test 0" aus
        test(i);
        System.out.println(i.get(0)); // gibt "Test 1" aus
    }

    private static void test(ArrayList<String> i1) {
        i1.set(0, "Test 1");
    }

}

Du könntest von ArrayList erben und dann die set-Methode unterbinden. Dann gibt es jedes Mal einen Fehler beim Aufruf von set.
Java:
class MyArrayList<E> extends ArrayList<E>
{
    public E set(int index, E element)
    {
        throw new RuntimeException("never use set!");
    }
}


Oder du clonest dir die ArrayList (shallow .clone() oder deep copy).

Klassen, welche nicht verändert werden können, heißen immutable (String/Integer/...).
 

Joah

Mitglied
Oder gleich Collections.unmodifieableList nutzen ;)
Hmm kannte ich noch nicht. Aber irgendwie macht diese Methode wenig Sinn für mich.
Wenn ich nämlich weiß, dass die aufgerufene Methode meine Liste verändert, dann übergebe ich einfach eine Kopie.
Mir fällt nur sehr wenig ein wo man sowas gebrauchen könnte.
Außerdem verstehe ich nicht, warum die Methode ein Objekt von List zurückgibt. Gibt's hier nicht ne Klasse, welche von List erbt und z.B. UnmodifieableList heißt?

Aber nochmal zurück zur Frage. Ich denke der Fragensteller will eine Methode mit einer ArrayList aufrufen, ohne dass die ArrayList dabei verändert wird. Also muss eine Kopie erstellt werden. clone() wirft aber eine exception beim casten.
Deshalb könnte man es wie folgt lösen:
Java:
test(new ArrayList<Integer>(i));
Dann gibt es keine exception und die aufgerufene Methode kann die ArrayList bearbeiten wie sie will...
 

mrBrown

Super-Moderator
Mitarbeiter
Hmm kannte ich noch nicht. Aber irgendwie macht diese Methode wenig Sinn für mich.
Wenn ich nämlich weiß, dass die aufgerufene Methode meine Liste verändert, dann übergebe ich einfach eine Kopie.
Mir fällt nur sehr wenig ein wo man sowas gebrauchen könnte.

Immer dann, wenn du verhindern willst, dass wer auch immer diese Liste bekommt, sie nicht verändert. Oft weißt du nicht, wer sie bekommt, solange nicht die gesamte Code-Basis nur von dir stammt. Meistens bei Rückgaben benutzt, zB bei Gettern.

Außerdem verstehe ich nicht, warum die Methode ein Objekt von List zurückgibt. Gibt's hier nicht ne Klasse, welche von List erbt und z.B. UnmodifieableList heißt?
Wenn, müsste sie Supertyp von List sein, aber nein, gibt es leider nicht.


clone() wirft aber eine exception beim casten.
Welche Exception wirft clone denn, wenn man damit eine ArrayList klont und auf ArrayList castet?
 

Joah

Mitglied
Wenn, müsste sie Supertyp von List sein, aber nein, gibt es leider nicht.
List wäre die Basisklasse und UnmodifieableList die erbende Klasse...
Welche Exception wirft clone denn, wenn man damit eine ArrayList klont und auf ArrayList castet?
Compiler warning, nicht Exception sorry...
Code:
warning: [unchecked] unchecked cast
Java:
ArrayList<Integer> al = new ArrayList<>();
al = (ArrayList<Integer>)al.clone();
 

Joah

Mitglied
Sinnvoller wäre es aber andersrum.
Abgesehen von der Benennung beschriebst du nämlich grad die aktuelle Situation, Collections.unmodifieableList gibt eine UnmodifiableList zurück, die Subtyp von List ist
Ja genau. UnmodifiableList wäre Subtyp von List, da UnmodifiableList ein Spezialfall von List ist.
Tatsächlich ist es aber so, dass List ein Interface ist...
Also gar keine Erbung von List :p

Hier der Quellcode von Collections.java
 

mrBrown

Super-Moderator
Mitarbeiter
Ja genau. UnmodifiableList wäre Subtyp von List, da UnmodifiableList ein Spezialfall von List ist.
Tatsächlich ist es aber so, dass List ein Interface ist...
Deshalb ist UnmodifiableList Subtyp von List, nicht wäre. Ob eins und welches davon ein Interface ist, ist für Sub-/Super-Typ-Beziehung egal.

Rein auf Typ-Ebene wäre es sinnvoller, wenn List ein Subtyp von ImmutableList ist (oder besser MutebleList Subtyp von List), wobei der Supertyp nur Lesenden Zugriff zulässt. Dann lässt sich das ganze auch über den statischen Typ abbilden, nicht nur über de dynamischen.
 
Zuletzt bearbeitet:

Joah

Mitglied
Deshalb ist UnmodifiableList Subtyp von List, nicht wäre. Ob eins und welches davon ein Interface ist, ist für Sub-/Super-Typ-Beziehung egal.

Rein auf Typ-Ebene wäre es sinnvoller, wenn List ein Subtyp von ImmutableList ist (oder besser MutableList Subtyp von List), wobei der Supertyp nur Lesenden Zugriff zulässt. Dann lässt sich das ganze auch über den statischen Typ abbilden, nicht nur über de dynamischen.
Also soweit ich mich an mein Studium erinnern kann, findet Vererbung nur bei extends statt. Außerdem gibt es Vererbung ja nur bei Klassen und ein Interface ist keine Klasse. https://www.java-tutorial.org/vererbung.html
Gerne lasse ich mich eines besseren belehren...

Mal angenommen List sei eine Klasse und List würde von ImmutableList erben (was du als sinnvoller erachtest).
Zitat:
Rein auf Typ-Ebene wäre es sinnvoller, wenn List ein Subtyp von ImmutableList ist (oder besser MutableList Subtyp von List)

Sorry das würde absolut kein Sinn machen. List ist die Generalisierung von ImmutableList und MutableList. Deshalb muss List die Basisklasse sein.
Wobei es die Klasse MutableList gar nicht gibt...

Wenn man es machen würde wie du gesagt hast, könnte man sprechen:
MutableList ist eine ImmutableList.
Oder:
Eine veränderbare Liste ist eine unveränderbare Liste.
Es macht keinen Sinn...
 

mrBrown

Super-Moderator
Mitarbeiter
Also soweit ich mich an mein Studium erinnern kann, findet Vererbung nur bei extends statt. Außerdem gibt es Vererbung ja nur bei Klassen und ein Interface ist keine Klasse. https://www.java-tutorial.org/vererbung.html
Gerne lasse ich mich eines besseren belehren...
Ich habe nirgends "Vererbung" geschrieben, sondern nur von Subtyp und Supertyp.
Wenn ich Vererbung im Sinne von Java-Vererbung meinen würde, würde ich das auch deutlich schreiben ;)
extends gibts btw auch bei Interfaces, interface SubInterface extends SuperInterface.


Sorry das würde absolut kein Sinn machen. List ist die Generalisierung von ImmutableList und MutableList. Deshalb muss List die Basisklasse sein.
Wobei es die Klasse MutableList gar nicht gibt...
Das es ist Listen nicht gibt ist klar, deshalb schrieb ich "wäre sinnvoller".

Ausgehende von ImmutableList ---|> List:

Code:
List list = new ImmutableList();// Wäre zulässig, der statische Typ ist also eine Veränderbare Liste, und der Nutzer weiß nicht, dass die Liste eigentlich Immuteable ist

ImmutableList imList = new List(); // Ginge nicht, ich kann meine muteable List nicht so übergeben, dass der Nutzer sie nicht verändern darf, sondern muss immer auch den dynamischen Typ anpassen

ImmutableList imList = ...;
boolean added =  imList.add(42); //Ich kann ganz normal alle Methoden aufrufen, und merke erst zur Laufzeit, dass es schief geht.

Und dann im Gegensatz dazu das ganze andersrum (Immutable mal zu Readonly geändert, das passt besser), List ---|> ReadonlyList:

Code:
List list = new ReadonlyList();//Ginge nicht. Eine (immutable) ReadonlyList kann ich nicht einfach als (mutable) List benutzen

ReadonlyList list = new List(); // Jede veränderliche Liste kann ich genauso nutzen wie eine unveränderliche - nämlich nur lesend und nicht verändernd

ReadonlyList list = ...;
boolean added =  list.add(42); //Geht nicht, ReadonlyList böte keine Methoden zum addieren an

List mutList = ...;
boolean added =  list.add(42); //Ginge, nur List bietet Methoden zum ändern an

Also: der Compiler lässt Änderungen an der Liste nur zu, wenn es explizit eine List ist. Ist es nur eine ReadonlyList, sind keine Änderungen möglich. Ich kann aber allem, was eine Liste nicht verändern will (also als statischen Typ ReadonlyList hat), jede Liste zuweisen.

Im Vergleich zu der aktuellen Variante:
Der Compiler hat keine Prüfmöglichkeit, deshalb kann ich über egal welchen statischen Typ immer die Liste ändern (was u.U. dann zur Laufzeit explodiert). Ich weiß nur in manchen Fällen schon vorher, dass es zur Laufzeit explodiert (nämlich dann, wenn es als ImmutableList deklarier ist), bekomm dabei aber keinerlei Unterstützung seitens IDE, Compiler oder sonstigem, sondern muss es mir merken.


Das Konzept gibts z.B. mit ReadOnlyProperty in JavaFX oder mit List & MutableList in kotlin
 

Neumi5694

Top Contributor
Hmm kannte ich noch nicht. Aber irgendwie macht diese Methode wenig Sinn für mich.
Wenn ich nämlich weiß, dass die aufgerufene Methode meine Liste verändert, dann übergebe ich einfach eine Kopie.
Mir fällt nur sehr wenig ein wo man sowas gebrauchen könnte.
Für das in diesem Thread beschriebene Problem ist sie tatsächlich wenig sinnvoll. Er will ja explizit innerhalb der Methode etwa in der Liste ändern (sortieren z.B.), ohne dass es nach außen dringt. Dafür ist ein Kopie unumgänglich.
Die Methode ist sinnvoll als Rückgabetyp, damit man eben KEINE Kopie anlegen muss oder eben um zu verhindern, dass man versehentlich mal was daran ändert, dann wird sofort eine Exception geschmissen.
Java:
    public List<String> getResult() {
        return Collections.unmodifiableList(Arrays.asList("a", "b", "c")); //Damit jemand das Ergebnis ändern kann, muss er eine Kopie anlegen.
    }
//validvalues kann in der Klasse nirgendwo mehr geändert werden
    private static Set<EnumType> validValues = Collections.unmodifiableSet(EnumSet.of(EnumType.Value1, EnumType.Value2));
 

Joah

Mitglied
Ah ich glaube jetzt habe ich dich verstanden @mrBrown
Mal angenommen es gibt eine Methode, die eine ImmutableList entgegen nimmt:
Java:
void moh(ImmutableList il){}
und die will man jetzt mit ArrayList aufrufen. Dann muss man ArrayList erst konvertieren...

Und ich glaube genau deshalb haben sie die ImmutableList nicht public gemacht.
Würde also doch Sinn machen was die gemacht haben...

@Neumi5694 ja da machts Sinn...
 

mrBrown

Super-Moderator
Mitarbeiter
Ah ich glaube jetzt habe ich dich verstanden @mrBrown
Mal angenommen es gibt eine Methode, die eine ImmutableList entgegen nimmt:
Java:
void moh(ImmutableList il){}
und die will man jetzt mit ArrayList aufrufen. Dann muss man ArrayList erst konvertieren...

Und ich glaube genau deshalb haben sie die ImmutableList nicht public gemacht.
Würde also doch Sinn machen was die gemacht haben...
In der jetzigen Implementierung: Ja, ImmutableList public zu machen, wäre sinnlos, da es keine Einschränkung von Methoden über den Typ gibt und man immer erst konvertieren muss.

Würde es aber einen Supertyp "ReadonlyList" von List geben, der nur lesenden Methoden hat, sähe das ganze aber so aus:
Java:
void moh(ReadonlyList list){
//nur lesender Zugriff möglich
}
...
moh(new ArrayList()); //möglich, da ArrayList Subtyp von ReadonlyList

Für das in diesem Thread beschriebene Problem ist sie tatsächlich wenig sinnvoll. Er will ja explizit innerhalb der Methode etwa in der Liste ändern (sortieren z.B.), ohne dass es nach außen dringt. Dafür ist ein Kopie unumgänglich.
Das spricht aber auch nicht dagegen, eine unmodifieableList zu übergeben - der Aufrufer will schließlich auch nicht, dass die Liste geändert wird ;)
 

Neumi5694

Top Contributor
Das spricht aber auch nicht dagegen, eine unmodifieableList zu übergeben - der Aufrufer will schließlich auch nicht, dass die Liste geändert wird ;)
Kann er natürlich machen, es bringt nur nichts, falls die Methode niemals die Ursprungsliste verändern darf. So oder so muss er dann in der Ursprungsmethode eine Kopie anlegen.
Nur zum Testen (JUnit z.B.) der Methode ist es sinnvoll dank der Exception bei Schreibzugriff auf die Ursprungsliste.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
M ArrayList oder LinkedList Allgemeine Java-Themen 10
C Sortieren und Selektieren einer ArrayList<Point3D> Allgemeine Java-Themen 6
A Einzelne Objekte und Unterobjekte einer ArrayList ausgeben Allgemeine Java-Themen 53
T Remove bei ArrayList funktioniert nicht Allgemeine Java-Themen 2
B Type mismatch: cannot convert from Graph.Edge to ArrayList<Graph.Edge> Allgemeine Java-Themen 21
R ArrayList Allgemeine Java-Themen 4
G jToggleButton in Array/ArrayList Allgemeine Java-Themen 12
J ArrayList, ganze Zeilen löschen oder überspringen Allgemeine Java-Themen 4
L ArrayList sortieren Allgemeine Java-Themen 2
C ArrayList Problem Allgemeine Java-Themen 3
O Datentypen Wie kann ich den Typ einer ArrayList abfragen ? Allgemeine Java-Themen 7
S Best Practices CopyConstrutor mit ArrayList Allgemeine Java-Themen 1
S ArrayList Design Allgemeine Java-Themen 4
S Array dynamisieren oder ArrayList verwenden? Allgemeine Java-Themen 17
L ArrayList mit String Arrays in ein Array umwandeln Allgemeine Java-Themen 1
H Elemente aus ArrayList in Array speichern Allgemeine Java-Themen 8
MiMa Person in einer Arraylist hinzugügen mit Prüfung ? Allgemeine Java-Themen 6
X Adjazenzliste ohne ArrayList Allgemeine Java-Themen 6
X Output von ArrayList Allgemeine Java-Themen 3
H Stream in ArrayList umwandeln Allgemeine Java-Themen 2
H Mehrere Datentypen in einer Arraylist speichern Allgemeine Java-Themen 9
H Arraylist mit anderer ArrayList überschreiben Allgemeine Java-Themen 17
MiMa ArrayList sortieren?? Allgemeine Java-Themen 5
Curtis_MC Pointer mit ArrayList vergleichen Allgemeine Java-Themen 6
F ArrayList`s in Klassen mit Getter/Setter Allgemeine Java-Themen 8
W Array vs. ArrayList vs. HashMap Allgemeine Java-Themen 20
F Arraylist vollständig abspeichern und laden Allgemeine Java-Themen 1
R Arraylist in andere Klasse leiten und bearbeiten Allgemeine Java-Themen 10
D ArrayList Indexlänge ändern Allgemeine Java-Themen 2
E Elemente innerhalb einer ArrayList vergleichen Allgemeine Java-Themen 33
N Mehrdimensionale ArrayList mischen Allgemeine Java-Themen 10
S JTable - mehrere ausgewählte Rows in ArrayList Allgemeine Java-Themen 5
MiMa Date aus einer ArrayList<Date> holen ?? Allgemeine Java-Themen 5
MiMa ArrayList Rückgabewerte aus einer Funktion Allgemeine Java-Themen 15
L CSV File lesen, in ArrayList speichern und ausgeben Allgemeine Java-Themen 3
M Was geschieht mit Java-Klasse, die aus ArrayList entfernt wird? Allgemeine Java-Themen 10
M Methoden Generische Methode für ArrayList Allgemeine Java-Themen 7
T Collections ArrayList Sortieren Allgemeine Java-Themen 4
P GUI: ArrayList anzeigen funktioniert nicht Allgemeine Java-Themen 5
H ArrayList: Leere Elemente finden? Allgemeine Java-Themen 2
GreenTeaYT Verständnisprobleme zur Arraylist Allgemeine Java-Themen 1
T Methoden Methode zum durchsuchen einer ArrayList Allgemeine Java-Themen 8
K ArrayList sortieren Allgemeine Java-Themen 16
A Bestimmte Inhalte aus ArrayList 1 in ArrayList 2 kopieren Allgemeine Java-Themen 6
S Mehrdimensionales ArrayList ins HashSet Allgemeine Java-Themen 10
C ArrayList Allgemeine Java-Themen 8
Streeber Probleme mit AWT-EventQueue: ArrayList Elemente hinzufügen Allgemeine Java-Themen 1
F Methoden Arraylist weiterverwenden nach methoden Aufruf Allgemeine Java-Themen 2
Z NullPointerException beim Schreiben einer ArrayList in eine Datei Allgemeine Java-Themen 6
L Von ArrayList abgeleitete Klasse nur mit bestimmten Objekten füllen Allgemeine Java-Themen 1
K Array in ArrayList Allgemeine Java-Themen 16
Paul15 2D Arraylist in Jtable Allgemeine Java-Themen 1
Paul15 Arraylist 2D Allgemeine Java-Themen 8
B ArrayList in ein Objekt legen Allgemeine Java-Themen 1
Neumi5694 Datentypen ArrayList vs TreeMap Allgemeine Java-Themen 6
F ArrayList Allgemeine Java-Themen 11
X ArrayList will nicht so wie ich will. Hilfe Allgemeine Java-Themen 8
N ArrayList in eigenem Object nicht richtig serialisierbar Allgemeine Java-Themen 14
M ArrayList mit verschiedenen Datentypen in String konvertieren Allgemeine Java-Themen 10
Z Elemente einer ArrayList von rechts wegnehmen Allgemeine Java-Themen 5
W Arraylist Text Suchen und Datei löschen Allgemeine Java-Themen 5
R ArrayList und HashMap Allgemeine Java-Themen 7
T ArrayList zeilenumbruch entfernen Allgemeine Java-Themen 13
D Arraylist/For Schleife/Scanner Allgemeine Java-Themen 30
E ArrayList Anzahl der gleichen Elemente Allgemeine Java-Themen 4
Doopy ArrayList plötzlich leer Allgemeine Java-Themen 2
D Arraylist eigener Klasse an iReport übergeben Allgemeine Java-Themen 7
L ArrayList Inhaltstyp. Allgemeine Java-Themen 5
Z Klassen ArrayList selbst machen Allgemeine Java-Themen 5
J Arraylist speichern und laden? Allgemeine Java-Themen 5
C Generics Objekt in ArrayList Allgemeine Java-Themen 2
D ArrayList index auf gültigkeit prüfen Allgemeine Java-Themen 12
M ArrayList<String> Frage Allgemeine Java-Themen 7
O ArrayList kaputt?! Allgemeine Java-Themen 5
M ArrayList<Foo> in ein Foo[] konvertieren? Allgemeine Java-Themen 8
Bananabert Abstract ArrayList Allgemeine Java-Themen 4
A Collections Array-Elemente in ArrayList kopieren ohne Schleife Allgemeine Java-Themen 7
O ArrayList - Serialisierungs-Problem Allgemeine Java-Themen 11
M JTable + ArrayList Allgemeine Java-Themen 3
M Datentypen ArrayList in Integer konvertieren Allgemeine Java-Themen 3
O Collections ListIterator gibt Inhalt von ArrayList nicht aus Allgemeine Java-Themen 3
Madlip Variablen 3 Werte aus ArrayList und weiter ... Allgemeine Java-Themen 4
S arraylist nach n. Eintrag numerisch Sortiren Allgemeine Java-Themen 5
O Problem beim Auslesen einer Arraylist von JComboBoxen Allgemeine Java-Themen 2
R Threads korrekte Synchronisation bei Vector und ArrayList Allgemeine Java-Themen 6
M Kovariante Rückgabewerte mit ArrayList Allgemeine Java-Themen 3
H LinkedList<LinkedList<String>> nach ArrayList<ArrayList<String>> ? Allgemeine Java-Themen 9
E NetBeans Vector durch ArrayList ersetzen Allgemeine Java-Themen 4
Maxim6394 Problem mit ArrayList Allgemeine Java-Themen 5
E Berechnung in Arraylist Allgemeine Java-Themen 10
E ArrayList mit unbekannter Größe Allgemeine Java-Themen 8
V Fork Join bei Arraylist Allgemeine Java-Themen 6
H Fehler in Arraylist Allgemeine Java-Themen 2
S Datensätze in eine ArrayList<Movie> speichern Allgemeine Java-Themen 13
S Alle Kombinationen aus ArrayList - Potenzmenge Allgemeine Java-Themen 7
V ArrayList vergleichen mit .equals? Allgemeine Java-Themen 13
J ArrayList-Problem Allgemeine Java-Themen 16
S Von einer ArrayList in die andere schreiben? Allgemeine Java-Themen 6
S ArrayList<JLabels> "malen" Allgemeine Java-Themen 4
E ArrayList in ArrayList, Referenzierungsproblem Allgemeine Java-Themen 7

Ähnliche Java Themen

Neue Themen


Oben