listIterator()-Methode gibt kein Objekt aus, warum?

oraclin25

Erfahrenes Mitglied
Hallo zusammen,

die Methode listIterator() irgendeiner List-Implementation gibt den Typ ListIterator als Referenztyp aus.

ArrayList<String> stringListe = new ArrayList<String>("eins","zwei");
ListIterator<String> stringListIterator = stringListe.listIterator();

zeigt die Referenzvariable stringListIterator auf irgendein Objekt? Zeigt sie überhaupt auf irgendwas?

Ich bin etwas verzweifelt aus folgendem Grund:
stringListeIterator.add("null") fügt "null" in die stringListe vorne hinzu. Wie ist das von stringListe referenzierte Objekt mit dem von stringListeIterator referezierten Objekt "verbunden", wenn überhaupt?

Gibt es eigentlich ein Stichwort für solche Methoden(Methoden, die nach deren Aufruf kein extra Objekt erzeugen)?

Vielen Dank für Eure Hilfe.

Viele Grüße aus Rheinland,

Eure Ratna
 
Hi

ich bin mir nicht sicher, ob ich deine Frage(n) richtig verstehe.

listIterator()-Methode gibt kein Objekt aus, warum?
...
die Methode listIterator() irgendeiner List-Implementation gibt den Typ ListIterator als Referenztyp aus.
"zurück". Ausgeben, zB. am Bildschirm, tut die Methode gar nichts, und soll sie auch nicht.

zeigt die Referenzvariable stringListIterator auf irgendein Objekt? Zeigt sie überhaupt auf irgendwas?
Natürlich.
Die Variable stringListIterator referenziert ein Objekt vom vom Typ ListIterator<>,
das die Methode .listIterator() von stringListe erzeugt hat
Gibt es eigentlich ein Stichwort für solche Methoden(Methoden, die nach deren Aufruf kein extra Objekt erzeugen)?
Methoden, die kein Objekt returnen, haben
a) Returntyp void
b) Returntyp int, float etc. (ob man solche einfachen Variablen Objekte nennen kann ist subjektiv, ich tus nicht)
c) oder returnen null (nicht den String "null", sondern null wie in "kein objekt").

Aber so eine Methode hast du nicht. listIterator() von stringListe gibt ein ganz echtes
existierendes Objekt zurück. Es kann nicht anders, nur echte Objekte oder null. Methoden
wie die, für die du ein Stichwort suchst, gibt es nicht.

Ich bin etwas verzweifelt aus folgendem Grund:
stringListeIterator.add("null") fügt "null" in die stringListe vorne hinzu. Wie ist das von stringListe referenzierte Objekt mit dem von stringListeIterator referezierten Objekt "verbunden", wenn überhaupt?
EIn Iterator für eine ArrayList ist prinzipiell dafür gedacht, alle Elemente der ArrayList von vorn bis hinten durchzulaufen und sich dabei selber die Position zu merken, ohne dass du das musst. Prinzipiell gibts so Methoden wie gibMirDasAktuelleElement() und weiter() und gibtsNochEinElementOderNicht), nur heißen die Methoden anders. Sowas wie eine for-Schleifen überschneidet sich sehr mit dem Sinn eines Iterators, Iteratoren haben aber etwas mehr/andere mögliche Anwendungsgebiete (geht hier zu weit).

Das IteratorObjekt hat in sich, als Membervariablen, mindestens eine Referenz auf die originale ArrayList, und eine Positionsnummer.

Zum eigentlichen Durchlauf-Sinn bietet der Iterator von ArrayLists zusätzlich auch an, Elemente einzufügen bzw. zu löschen, so wie add() und remove() auf der originalen ArrayList. add() und remove() vom Iterator tun prinzipiell nichts anderes, also add() und remove() der ArrayList aufzurufen, die wird mithilfe der intern gespeicherten Referenz gefunden.

Erst weiterlesen wenn bisher alles verstanden wurde:
Der Iterator kennt seine ArrayList, aber die Al. kennt den I. nicht. Wenn man direkt bei der Al Elemente einfügt kann die Al das dem I nicht mitteilen, und weil der es damit überhaupt nicht weiß, könnte er mit seiner Positionsnummer in der jetzt veränderten Al durcheinanderkommen. zB. wenn man nach der Al-Änderung weiter die Elemente durchlaufen will, dass man dann ein paar die man schon hatte wieder bekommt, oder ein paar ausgelassen werden. Das ist auch ausdrücklich in der Doku beschrieben: Nach Änderungen auf der AL darf man sich auf bestehende It's praktisch nicht mehr verlassen, man kann sich maximal neue erzeugen. Unter anderem deswegen hat der It auch add() und remove(): Wenn man mit denen in der Al herumändert weiß es der It und passt seine Position entsprechend an, sodass jedes Element wirklich nur/genau einmal durchlaufen wird.
 
Zuletzt bearbeitet:
Ich lösche meinen Nonsense, denn ich habe den ListIterator übersehen. Bitte das nächste mal in Code-Tags packen, kann man einfach besser lesen.

Aber ich gebe dennoch mal mein Beispiel an:

Java:
package de.tutorials.list;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class IteratorTest {

    public void run() {
        List<String> stringListe = new ArrayList<String>();
        stringListe.add("eins");
        stringListe.add("zwei");

        ListIterator<String> stringListeIterator = stringListe.listIterator();
        while (stringListeIterator.hasNext()) {
            String aktuellesItem = stringListeIterator.next();
            System.out.println(aktuellesItem);
        }
    }

    public static void main(String[] args) {
        new IteratorTest().run();
    }
}

Ansonsten hatte ich ähnliches wie sheel geschrieben.

Noch zu den int, boolean, float und double: Das sind primitive Datentypen, es handelt sich dabei nicht um Objekte. Das ist auch daran zu erkenne, dass man auf Variablen diesen Typs keine Methoden aufrufen oder Eigenschaften abholen kann.
 
Zuletzt bearbeitet:
Hallo sheel, hallo saftmeister,

danke für die rasche und ausführliche Antwort.

Das IteratorObjekt hat in sich, als Membervariablen, mindestens eine Referenz auf die originale ArrayList, und eine Positionsnummer.

Dieser Satz hat mir sehr geholfen. Ich hatte halt gedacht, "äääär, die Referenzvariable stringIterator kann echt so viel? Zeigt sie denn etwa auf das ArrayList-Objekt? Kann nicht sein, sie sind von unterschiedlichem Typ. Aber wie kann sie so schlau sein, das sie Sachen noch in das ArrayList-Objekt hinzufügen kann, sie muss doch irgenwie mit dem ArrayList-Objekt kommunizieren können?"

sheel, Du hast es erraten, dass ich ein bisschen Internas verstehen wollte, wie das so funktioniert.

Ich finde es nur ärgerlich, warum ich solche Informationen nur sehr schwer im Netz finde. Wo steht es zum Beispiel, dass ein Iterator-Objekt eine Membervariable besitzt. In der API-Doku ist es sogar so, dass lediglich 3 Methoden zum Iterator existieren :-(

Viele Grüße aus Rheinland,

Eure Ratna
 
Das muss eigentlich nirgends stehen. Es kann nur so sein ;-) Nicht umsonst kannst du ein gültiges Iterator-Objekt auch nur von einer Collection (in dem Falle halt eine List) bekommen. Iterator bzw. dessen Bruder ListIterator sind ja nur Interfaces, die selbst keine Logik haben, sondern nur die API zur Verfügung stellen. Bevor du stundenlang im Netz suchst, schnapp dir die IDE deiner Wahl und starte ein kleines Programm, in dem du es debuggst.

Im Anhang kannst du die Debug-Perspektive der Eclipse sehen. Ich habe mal die die Variable-View anzeigen lassen, dann siehst du, dass das Objekt stringListeIterator vom Typ ArrayList$ListItr ist, also eine öffentliche private eingebettete Klasse ListItr in der Klasse ArrayList.

Diese ListItr-Klasse implementiert das Interface ListIterator. Wenn du auf einem Objekt vom Typ ArrayList (was das Interface List implementiert), die Methode listIterator() aufrufst, bekommst du ein Objekt der genannten Klasse ListItr zurück, die natürlich, weil sie in ArrayList eingebettet ist, auf alle Member-Variablen (auch die privaten) von ArrayList zugreifen kann.

Das kostet dich 5 Min Arbeit (wenn überhaupt), das Programm runter zu tippen und zu debuggen. Dann bist du direkt in die API eingetaucht und verstehst was dort passiert. Theorie hin oder her, schön das es API-Dokumentationen gibt, aber sowas möchte ich doch live am "Patienten" sehen ;-)
 

Anhänge

  • eclipse-debug-listiterator.png
    eclipse-debug-listiterator.png
    60,9 KB · Aufrufe: 9
Zuletzt bearbeitet:
hast Recht, saftmeister. Übrigens, in deinem Snapshot ist dieser Value ArrayList$ListItr. Ist des eine Art interne Implementierung, die uns nicht zu interessieren hat? Ich verstand nicht, was Du mit eingebettet meintest.
 
hast Recht, saftmeister. Übrigens, in deinem Snapshot ist dieser Value ArrayList$ListItr. Ist des eine Art interne Implementierung, die uns nicht zu interessieren hat? Ich verstand nicht, was Du mit eingebettet meintest.

Ich habe mein Posting schon korrigiert. ListItr ist eine private Klasse in der Klasse ArrayList:

Java:
public class ArrayList
{
  private class ListItr implements ListIterator
  {
    ...
  }
}

Das bedeutet auch, dass du ListItr nicht direkt selbst instanziieren kannst, sie kann nur innerhalb ArrayList instanziiert werden. Beispiel:

Java:
public class ArrayList
{
  private class ListItr implements ListIterator
  {
    ....
  }

  public void machWas()
  {
    ListItr iterator = new ListItr(); // Das hier geht
  }
}

ArrayList.ListItr iterator = new ArrayList.ListItr(); // Das hier geht nicht.

Und genau, es interessiert eigentlich nicht, wichtig ist hier nur, dass ListItr das Interface ListIterator implementiert und somit die Instanz auf ListIterator gecastet werden kann. ListIterator ist ja eine öffentliche Schnittstelle und kann daher überall verwendet werden.

Ich hoffe, ich hab es einigermaßen verständlich erklärt.

Im übrigen: Beim JDK (jedenfalls dem von Oracle) ist der Source-Code der Runtime dabei (src.zip) und wird standardmäßig mit installiert. Diese Zip kann man als Source-Attachment an die rt.jar anhängen und damit in den Source-Code der Runtime reindebuggen und auch ansehen. Daher kann ich den Sourcecode der Klasse ArrayList in meiner Eclipse sehen.
 
edit: Zwei Betiräge verpasst :eek: ... naja, vllt. hilfts noch irgendwie

Noch was zu der Doku:

a) Wie saftmeister schon sagt ist bei der ArrayList-Seite nicht angegeben, von welcher Klasse die Iteratorobjekte sind, nur dass zumindest ein Interface mit den passenden Methoden bei dieser Klasse eingebunden ist. Der Name und genaue Code dieser Klasse sind evt. nicht in jeder Java-Version gleich, und vermutlich nirgends in der Online-Doku zu finden. Es gibt die Klasse halt, der Code von ArrayList verwendet sie, sie hat mindestens die Interfacemethoden die xyz machen, und mehr muss man eigentlich auch gar nicht wissen

b) Das Interface Iterator hat, wie du sagst, nur drei Methoden, dabei kein add() usw.
Die Iteratorerzeuge-Methode bei ArrayList returned aber etwas mit Interface ListIterator.
ListIterator erbt von Iterator, jede Klasse mit ListIterator eingebunden hat also (auch) die Iterator-Methoden.
Und ListIterator hat add() usw. zusätzlich
http://docs.oracle.com/javase/7/docs/api/java/util/Iterator.html
http://docs.oracle.com/javase/7/docs/api/java/util/ListIterator.html

c) Soviel zu den Methoden. Woher man jetzt die Membervariablen kennt?
Eigentlich gar nicht, außer man schaut sich den Code vom Iterator (von der tatsächlichen
Klasse) an. Meine Aussage, dass zumindest ArrayList-Referenz und Positionszähler drin
sein müssen, basiert nur darauf, dass es keine Möglichkeit gibt, so eine Iteratorklasse
ohne diese zwei Variablen zu schreiben. Irgendwie muss der Iterator die ArrayListe ja
finden können, und irgendwie muss er auch wissen, wieviel Objekte schon besucht
wurden.
Kleinere Variationen gehn schon, zB. zählen wie viel Objekte man noch besuchen muss,
statt wieviel man schon hat, aber ganz ohne geht nicht.

edit2: Da die Iteratorklasse Teil der ArrayList ist ist eine eigene Referenzvar zur
ArrayList evt. doch nicht nötig :D Nicht-statische innere Objekte haben eine Referenz
zum oberen Objekt schon automatisch "eingebaut".
 
Zuletzt bearbeitet:
Zurück