ArrayList-iteration mit Prüfung auf instanceof durch switch case?

Alina_C

Mitglied
Hallo :meld:

Ich habe folgende Situation. Eine ArrayList kann verschiedene Arten von (, sagen wir mal, )Tieren aufnehmen. Nun sollen alle Methoden, die ein spezielles Tier (zb. Fisch mit schwimmen(); oder Vogel mit fliegen();) bereitstellt, getestet werden.

Ich denke normalerweiße würde man mit einer for Schleife durchiterieren, wobei jedesmal auf Fisch oder Vogel geprüft wird.
Java:
...
for (int x = 0; x < tierListe.size(); x++){
  if (tierListe.get(x) instanceof Vogel){
     tierListe.get(x).fliegen();
  }
  if (tierListe.get(x) instanceof Fisch){
     tierListe.get(x).schwimmen();
  }
}

...

Angenommen ich habe jetzt aber nicht nur diese zwei Arten von Tieren, sondern 10/20/oder gar 50 -
ich habe gehört es sei sinnvoller auf switch case zu setzen, wenn es viele Fallunterscheidungen gibt.
Aber wieviele sind "viele"? Und gilt das auch für ArrayLists mit instanceof-Operator in jeder case-Klausel?
Gibt es eine bessere Lösung als isntanceof? (Ich habe gelesen, dass die Benutzung davon nicht gut für die Performance sei) Wie wäre es mit if -Anweisungen in der Art
Code:
if(tierListe.get(x).getClass()=="Vogel")


::gerade bemerkt, dass getClass in diesem Fall nur class arrayListClasses zurückgibt :noe:
 
S

SlaterB

Gast
verwende eine gemeinsame Basisklasse, und sei es ein Wrapper der auf andere Objekte verweist,
und ordne jedem Objekt je nach Klasse einen bestimmten Wert eines Enums zu, dann geht auch switch leicht:
Java:
switch(tier.getType()) {
  case Vogel:
    ..
    break;
  case Fisch:
    ..
    break;

}
für tierspezifische Methoden muss man dann normalerweise casten,
haben bei dir alle Tiere die Methoden fliegen();, schwimmen(); usw?

---

besonders schlimm ist aber noch tierListe.get(x) 4x in deinem Code oder noch öfter zu schreiben,
speichere tierListe.get(x) in einer Variable tier in der Schleife und verwende dann überall tier

---

das Class-Objekt müsstest du mit Vogel.class usw. vergleichen,
die Klasse ArrayList sollte beim geposteten Code nicht erscheinen
 

Landei

Top Contributor
[c]switch[/c] kann keine Typunterscheidung vornehmen. Dein Code würde übrigens nicht funktionieren, er müsste ungefähr so aussehen:

Java:
...
for (int x = 0; x < tierListe.size(); x++){
  Tier tier = tierListe.get(x);
  if (tier instanceof Vogel){
     ((Vogel) tier).fliegen();
  }
  if (tier instanceof Fisch){
     ((Fisch) tier).schwimmen();
  }
}
...

Eleganter ist übrigens die "enhanced for-loop":

Java:
...
for (Tier tier : tierListe){
...

Wie man das Problem in der Praxis löst, hängt von den genauen Einsatzbedingungen ab. Oft liegt ein Designfehler vor, wenn du so eine Konstruktion mit mehr als drei, vier Unterklassen hast.


[edit]
Slaters Lösung gefällt mir nicht so toll. Den Typ einer Objekts kann ich mit
Code:
getClass()
ermitteln oder mit
Code:
instanceof
testen. Ein zusätzliches Enum-Feld dupliziert sozusagen die Typinformationen, und das ist in der Regel keine gute Sache. Es mag Anwendungsfälle geben, wo diese Technik ihre Berechtigung hat, im Allgemeinen würde ich versuchen, so etwas zu vermeinden.
[/edit]
 
Zuletzt bearbeitet:

Alina_C

Mitglied
Vielen Dank für die wertvollen Tipps.
Typecasting hatte ich vergessen, denn hier soll nicht jedes Tier fliegen/schwimmen können.

Landei, dürfte ich dich bitten etwas genauer auf den möglichen Designfehler einzugehen?
Jedes Objekt {erbt|implementiert} doch {von der|die} Oberklasse Tier.
Sollte man Tier noch weiter gliedern? E.g. in Säugetiere, Reptilien, Amphibien, Wirbeltiere...
Bin keine Biologin, aber es könnte doch auch den Fall geben, dass ein Tier ein Vogel und ein Saurier (sorry, mir fiel nichts ordentliches ein) ist...
Gibt es spezielle Bücher über solche Designfragen?
 
S

SlaterB

Gast
worin unterscheiden sich denn die 20 Tiere und mehr, brauchen die wirklich alle eine eigene Klasse, hat jeder individuelle Methoden?
man sieht ja auch an deinen if/else oder switch-Aufrufen wie unhandlich das ist,

statt z.B.
fliege(), schwimme(), gehe(), schleiche(), moonwalke() usw. reicht vielleicht generell eine Methode bewege(), die in allen Unterklassen passend befüllt ist, ob nun geflogen oder geschwommen wird,
das macht den Aufruf extrem komfortabler, die Unterscheidung fällt komplett weg,
unabhängig davon müssen es nicht vielleicht nicht so viele Klassen sein oder zumindest gemeinsame Mittelklassen wie eben für alle Flieger

oder noch eine Variante sind nur gewisse Klassen wie Flieger, die für verschiedene theoretische Endklassen genutzt werden,
Vögel, Drachen und fliegende Tomaten sind keine eigenen Klassen sondern Flieger-Objekte mit interner Konfiguration,
gerade dann auch bietet sich Enum zur internen Unterscheidung an, wenn die Klasse es selber nicht mehr her gibt,

aber meiner Meinung nach ist das auch bei einzelnen Klassen nicht zu verachten, allein um instanceof oder noch andere Aktionen mit den Class-Objekten zu vermeiden, etwa Key in einer Map, mit Enum kann man viel anstellen
 
Zuletzt bearbeitet von einem Moderator:

Gossi

Bekanntes Mitglied
statt z.B.
fliege(), schwimme(), gehe(), schleiche(), moonwalke() usw. reicht vielleicht generell eine Methode bewege(), die in allen Unterklassen passend befüllt ist, ob nun geflogen oder geschwommen wird,

Sehe ich genauso, würde dann auch eher sowas nehmen wie:

Java:
public class Tier {

     public void bewegen() {
          //Todo: Nothing
     }

}

Java:
public class Vogel extends Tier {

     @Override
     public void bewegen() {
          System.out.println("Ich flieeeeeege!");
     }

}
 

knucki

Aktives Mitglied
Hi, stell dir mal folgendes vor:

  • 1. Nehmen als Tier den Papageientaucher. Kann fliegen, schwimmen und tauchen. Kein Fisch.
  • 2. Nehmen als Tier den Pinuin. Kann schwimmen, tauchen aber nicht fliegen. Kein Fisch.
  • 3. Nehmen als Tier die Fledermaus/den Flughund. Kann fliegen. Kein Vogel.
  • 4. Nehmen als Tier den "fliegenden Fisch"(kann nicht wirklich fliegen, nur weit aus dem Wasser hüpfen, aber egal). Kann tauchen,schwimmen und fliegen. Kein Vogel

Wie würdest du das jetzt mit dieser Sicht angehen? Abstrakt denken dann programmieren.

Edit: Die Herren haben nun das vorweg genommen, wo ich dich durch nachdenken hinkriegen wollte. Also ignorier es
 

Gossi

Bekanntes Mitglied
Hi, stell dir mal folgendes vor:

  • 1. Nehmen als Tier den Papageientaucher. Kann fliegen, schwimmen und tauchen. Kein Fisch.

Java:
public class Tier {

     protected boolean fly;
     protected boolean swim;
     protected boolean dive;
     protected boolean run;

     public Tier() {
          fly = false;
          swim = false;
          dive = false;
          run = false;
     }

     public void move() {
          //Todo: Nothing
     }

     public boolean canFly() {
          return fly;
     }

     public boolean canSwim() {
          return swim;
     }

     public boolean canDive() {
          return dive;
     }

     public boolean canRun() { //oder canWalk
          return run;
     }

}

Java:
public class Vogel extends Tier {

     public Vogel() {
          super();
          fly = true;
     }

     @Override
     public void move() {
          System.out.println("Ich flieeeeeege!");
     }

     

}


Java:
public class Papageientaucher extends Vogel {

     public Papageientaucher() {
          super();
          swim = true;
          dive = true;
     }

     @Override
     public void move() {
          System.out.println("Ich tauschschwimfliege!");
     }

}

PS: Steinigt mich wenns falsch is...

PPS:
Testklasse:
Java:
public class Test {

	public static void main(final String[] args) {
		List<Tier> tierList = new ArrayList<Tier>();
		Papageientaucher ptauch = new Papageientaucher();
		Vogel vogel = new Vogel();
		tierList.add(ptauch);
		tierList.add(vogel);
		for (Tier tier : tierList) {
			tier.move();
		}
	}

}
 
Zuletzt bearbeitet:
N

nillehammer

Gast
Um noch mal zur Ursprungsfrage zurück zu kommen: In Java 7 gehen jetzt auch Strings als Bedingung für switch/case. Du könntest also mit getClass().getName() den Klassennamen ermitteln und darüber dann switchen.

Ansonsten ist Code, der so arbeitet sehr schlecht wart-/erweiterbar. Immer, wenn eine neue Klasse hinzukommt, musst du nämlich dran denken, an einer bestimmten Stelle Deinen Code anzupassen. In den meisten Fällen lässt sich solch ein Code mit einem besseren Design umgehen:
- Besser durchdachte Klassenhirarchie mit (abstrakten) Basisklassen
- Möglicherweise viele schmale Interfaces implementieren, statt von einer mächtig überfrachteten Basisklasse ableiten
- Vielleicht sogar auf Vererbung verzichten und mit Komposition arbeiten.
 
N

nillehammer

Gast
@Gossi: Wer ohne Fehler ist, werfe den ersten Stein. Ich bin zwar nicht ohne Fehler, werfe jetzt aber trotzdem mal ;).
In Deinem Post von heute 14:53 wäre wohl statt der leeren und relativ sinnfreien default-Implementierung der Methode bewegen eine abstrakte Basisklasse Tier mit abstrakter Methode bewegen besser gewesen, ungefähr so:
Java:
public abstract class Tier {
 
     public abstract void bewegen();

     .... 
}
Und Deine Lösung zu knucki's Anregungen ist grauenhaft. Die Methoden haben in Tier nix zu suchen und sollten besser mit Interfaces (Flyer#fly, Swimmer#swimm, Walker#walk) definiert werden. Ein fliegender Fisch würde dann bspw. Flyer und Swimmer implementieren.
 
Zuletzt bearbeitet von einem Moderator:
S

SlaterB

Gast
als Alternative zu den booleans von Gossi bietet sich auch hier einmal mehr Enums an,
jedes Objekt hat ein Set beliebig kombinierbarer Eigenschaften

andererseits natürlich auch nicht ganz schön, wenn man 5 Papageientaucher und 4 Pinguins hat,
genau darauf zu achten, wer welche Eigenschaften hat, nicht dass sich da etwas unterscheidet,

eigene Subklassen durchaus denkbar, wenn ohne neue Methoden, nur interne Konfiguration,
ohne nötiges switch, dann ja auch nicht ganz so gefährlich

falls aber Papageientaucher nur von einer bestimmten Methode erzeugt werden, ginge es auch ohne eigene Klasse
 

knucki

Aktives Mitglied
Ich weiss, für das wird mich nillehammer schlagen, aber des Verständnisses wegen, habe ich eine kleine Impl ohne Interfaces gemacht:

Java:
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class Tier {
  public final int               walk     = 0;
  public final int               crouch   = 1;
  public final int               run      = 2;
  public final int               swim     = 3;
  public final int               dive     = 4;
  public final int               fly      = 5;
  public final int               moonwalk = 6;

  private final Set<Integer>     moves    = new HashSet<Integer>();

  protected Map<Integer, String> movesX   = new HashMap<Integer, String>();

  public Tier() {
    movesX.put(walk, "gehen");
    movesX.put(crouch, "kriechen");
    movesX.put(run, "rennen");
    movesX.put(swim, "schwimmen");
    movesX.put(dive, "tauchen");
    movesX.put(fly, "fliegen");
    movesX.put(moonwalk, "Auf dem Mond laufen ^^");
  }

  public void addMove(final int move) {
    moves.add(move);
  }

  public Set<Integer> moving() {
    return moves;
  }

  public String movingX() {
    if (moves.isEmpty()) {
      return "Kann gar nix!";
    }
    final StringBuilder sb = new StringBuilder();
    sb.append("Ich kann: ");
    for (final int move : moves) {
      sb.append(movesX.get(move) + ", ");
    }
    return sb.substring(0, sb.lastIndexOf(","));
  }
}
Java:
public class Papageientaucher extends Tier {

  public Papageientaucher() {
    super();
    addMove(walk);
    addMove(crouch);
    addMove(swim);
    addMove(dive);
    addMove(fly);
  }

}

Java:
public class MoonwalkingTeletubbie extends Tier {
  public MoonwalkingTeletubbie() {
    super();
    addMove(walk);
    addMove(moonwalk);
  }
}
Java:
import java.util.ArrayList;
import java.util.List;

public class IchbineinTier {

  /**
   * @param args
   */
  public static void main(final String[] args) {
    final List<Tier> tiere = new ArrayList<Tier>();
    final Papageientaucher p = new Papageientaucher();
    tiere.add(p);
    final MoonwalkingTeletubbie m = new MoonwalkingTeletubbie();
    tiere.add(m);
    for (final Tier tier : tiere) {
      System.out.println(tier.movingX() + " und bin ein " + tier.getClass().getName());
    }

  }
}

Zu beachten ist, dass die Basisklasse maximal das implemetiert, was für Alle abgeleiteten Klassen gilt!

Nille darfst draufhauen :D
 
N

nillehammer

Gast
Wenn Dich jemand schlägt, halte auch die andere Wange hin (hab's heut mit der Bibel).
knucki hat gesagt.:
Java:
  public final int               walk     = 0;
  public final int               crouch   = 1;
  public final int               run      = 2;
  public final int               swim     = 3;
  public final int               dive     = 4;
  public final int               fly      = 5;
  public final int               moonwalk = 6;
 
  private final Set<Integer>     moves    = new HashSet<Integer>();
Wenn schon so, dann doch lieber -wie von SlaterB vorgeschlagen- mit enum und EnumSet.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
krgewb ArrayList allgemein halten Java Basics - Anfänger-Themen 6
M Ausgabe einer ArrayList ensteht nur als Hashcode, nicht als Objekt Java Basics - Anfänger-Themen 16
S Java: Wie sortiere ich eine ArrayList benutzerdefinierter Objekte nach einem bestimmten Attribut? Java Basics - Anfänger-Themen 2
J ArrayList in 2D-Array konvertieren. Java Basics - Anfänger-Themen 48
E Arrays in einer ArrayList miteinander vergleichen Java Basics - Anfänger-Themen 12
String in ArrayList umwandeln Java Basics - Anfänger-Themen 1
F Arraylist<String>Ein Wort pro Zeile Java Basics - Anfänger-Themen 6
J ArrayList vergleichen im spiel Mastermind Java Basics - Anfänger-Themen 2
Mugetsu35 ArrayList Update ohne Index Java Basics - Anfänger-Themen 6
W Objekte einer ArrayList in txt-datei schreiben mit Paths? Java Basics - Anfänger-Themen 2
Z Java ArrayList speichert falsche Daten ab bzw. gibt falsche Daten aus? Java Basics - Anfänger-Themen 42
W if-Abfrage bei ArrayList-Methodenaufrufen - Wie löse ich das? Java Basics - Anfänger-Themen 6
W ArrayList und toString Java Basics - Anfänger-Themen 17
volcanos Addition -> List<Integer> mit Arrays.asList() versus List<Integer>ArrayList<>() Java Basics - Anfänger-Themen 14
ArrayList mit unbekannter Menge an Arrays die Arrays vergleichen Java Basics - Anfänger-Themen 9
M 2d ArrayList durchgehen Java Basics - Anfänger-Themen 2
Blkckroll45 Arraylist Java Basics - Anfänger-Themen 6
H Interface Wieso "List<String> list = new ArrayList<>[…]" Java Basics - Anfänger-Themen 4
berserkerdq2 Geht collections.sort bei allen? Linkedhashset, ArrayList, HashSet etc. Java Basics - Anfänger-Themen 4
R Methoden Werte einer ArrayList als Parameter übergeben. Java Basics - Anfänger-Themen 4
L Dauerhaftes Speichern einer Eingabe bei einer ArrayList Java Basics - Anfänger-Themen 26
D Arraylist mit Komplexen Datentyp Java Basics - Anfänger-Themen 3
H Kompliziertes Sortieren einer ArrayList mit Objekten(Sortieren nach X und Y) Java Basics - Anfänger-Themen 11
T Permanentes speichern von Objekten in einer ArrayList Java Basics - Anfänger-Themen 6
volcanos List & ArrayList nach Familiennamen abfragen Java Basics - Anfänger-Themen 57
M static ArrayList in non-static Java Basics - Anfänger-Themen 12
berserkerdq2 Ich gebe eine ArrayList als List zurück per MEthode, wie kann ich nun aber die ArrayList speichern? Java Basics - Anfänger-Themen 46
M ArrayList<TreeNode<T>> fortlaufende Nummerierung der Elemente Java Basics - Anfänger-Themen 5
B Bungeecord | ProxiedPlayer wird nicht in ArrayList hinzugefügt Java Basics - Anfänger-Themen 1
S ArrayList Username und passwort mit JTextField eingaben abgleichen Java Basics - Anfänger-Themen 10
F Werte in einer Arraylist Zählen Java Basics - Anfänger-Themen 2
F Erste Schritte Zahlenreihe von Arraylist in 3erBlöcke sortiert in neue Arraylist Java Basics - Anfänger-Themen 2
M ArrayList mit einer Schleife befüllen Java Basics - Anfänger-Themen 2
F Methode ArrayList mit Eingabewert Java Basics - Anfänger-Themen 2
J ArrayList add methode selbst programmieren Java Basics - Anfänger-Themen 10
K Erste Schritte Wie schnell ist LinkedHashMap im Vergleich zur ArrayList, wenn alle Entries durchlaufen werden? Java Basics - Anfänger-Themen 47
thobren jtable arraylist Java Basics - Anfänger-Themen 12
N Exception beim Verwenden von Arraylist? Java Basics - Anfänger-Themen 10
P Schiebefix - ArrayList überschreibt Daten Java Basics - Anfänger-Themen 3
Zeppi OOP ArrayList Java Basics - Anfänger-Themen 2
P ArrayList Java Basics - Anfänger-Themen 4
L ArrayList auf 4 Elemente begrenzen Java Basics - Anfänger-Themen 56
C ArrayList sortieren nach bestimmten Buchstaben in den Wörtern Java Basics - Anfänger-Themen 13
S Arraylist<Object> mit verschiedenen Objects ausgeben Java Basics - Anfänger-Themen 3
J ArrayList auf bereits vorhanden eintrag prüfen Java Basics - Anfänger-Themen 5
M For Schleife/ArrayList Java Basics - Anfänger-Themen 12
L ArrayList<String> --> double[] array Java Basics - Anfänger-Themen 18
L Längstes Element einer ArrayList ausgeben Java Basics - Anfänger-Themen 9
S Aus verschachtelter ArrayList auf einen Wert zugreifen Java Basics - Anfänger-Themen 4
L Methoden ArrayList Werte hinzufügen und löschen Java Basics - Anfänger-Themen 32
M ArrayList in GUI ausgeben Java Basics - Anfänger-Themen 1
J Nur bestimmter Typ aus der ArrayList ausgeben. Java Basics - Anfänger-Themen 9
Bademeister007 Hallo Leute ich hab eine Frage zur ArrayList Java Basics - Anfänger-Themen 8
Bademeister007 Operatoren Alle Zahlen einer ArrayList die durch 5 teilbar ist Java Basics - Anfänger-Themen 2
S Objekt aus Arraylist in andere Arraylist kopieren? Java Basics - Anfänger-Themen 2
C Sortieren einer ArrayList Java Basics - Anfänger-Themen 2
krgewb ArrayList von ArrayList Java Basics - Anfänger-Themen 2
R ArrayList Problem Java Basics - Anfänger-Themen 6
jonny_2k12 Wie kann ich eine ArrayList aus einer Klasse in eine andere übergeben? Java Basics - Anfänger-Themen 21
O Namen (mit Umlauten und ß) in einer ArrayList suchen Java Basics - Anfänger-Themen 5
N Typebound Objekte einer Arraylist hinzufügen Java Basics - Anfänger-Themen 7
R Methoden ArrayList clonen wirft exception Java Basics - Anfänger-Themen 3
S ArrayList in andere Klasse übernhemen Java Basics - Anfänger-Themen 5
M Letztes Element einer ArrayList Java Basics - Anfänger-Themen 12
B Objektverwaltung mit ArrayList in einer seperaten Klasse Java Basics - Anfänger-Themen 24
I Sortiert eine HashMap nicht gleich wie eine ArrayList? Java Basics - Anfänger-Themen 1
I ArrayList erstellen innerhalb einer Zeile? Java Basics - Anfänger-Themen 3
L Iterieren durch eine ArrayList. Integer Array wird übergeben Java Basics - Anfänger-Themen 17
V Collections ArrayList mit Comparator sortieren Java Basics - Anfänger-Themen 16
D Collections Arrays in ArrayList abspeichern Java Basics - Anfänger-Themen 6
F java.util.ArrayList Java Basics - Anfänger-Themen 3
M ArrayList - Objekt kopieren und ändern Java Basics - Anfänger-Themen 11
M Zugriff auf eine ArrayList in einer anderen Klasse Java Basics - Anfänger-Themen 4
P Arraylist zu einem Array bringen mit Verschachtelung Java Basics - Anfänger-Themen 11
N Methode mit einer Arraylist Java Basics - Anfänger-Themen 106
I ArrayList - Methode zum Speichern eines Eintrags in einer Datei Java Basics - Anfänger-Themen 17
H ArrayList Java Basics - Anfänger-Themen 7
D public ArrayList(Collection<? extends E> c); Java Basics - Anfänger-Themen 2
M JTextField in ArrayList speichern Java Basics - Anfänger-Themen 4
C ArrayList mit return zurückgeben Java Basics - Anfänger-Themen 13
K Zahlenfolge ArrayList Java Basics - Anfänger-Themen 3
C Erste Schritte Frage zur ArrayList Java Basics - Anfänger-Themen 15
I Klassen Eine ArrayList<Long>, die sich automatisch sortiert Java Basics - Anfänger-Themen 20
F Array in ArrayList ablegen Java Basics - Anfänger-Themen 3
V ArrayList Java Basics - Anfänger-Themen 1
Z Runden Arraylist Java Basics - Anfänger-Themen 9
X Frage zur einer ArrayList in einer ArrayList Java Basics - Anfänger-Themen 5
F Arraylist als Pfadausgabe Java Basics - Anfänger-Themen 10
L Daten aus ArrayList in Datenbank durchsuchen Java Basics - Anfänger-Themen 5
L Objekt aus Textdatei in ArrayList speichern Java Basics - Anfänger-Themen 4
M Problem mit ArrayList Java Basics - Anfänger-Themen 32
X Objekte einer ArrayList richtig ausgeben? Java Basics - Anfänger-Themen 8
O Hashmap, ArrayList, LinkedList Java Basics - Anfänger-Themen 7
X Problem mit Arraylist in Arraylist Java Basics - Anfänger-Themen 2
O HashMap - ArrayList Java Basics - Anfänger-Themen 29
M UML-Klassendiagramm ArrayList Java Basics - Anfänger-Themen 1
O ArrayList oberflächig durchsuchen Java Basics - Anfänger-Themen 3
I "\n" aus ArrayList enfernen, aber wie?! Java Basics - Anfänger-Themen 4
V Collections Objekte einer ArrayList in der main() ausgeben Java Basics - Anfänger-Themen 9
Jackii ArrayList ausgabe ohne Dopplung Java Basics - Anfänger-Themen 11

Ähnliche Java Themen

Neue Themen


Oben