Java: Zugriff auf Attribute von Objekten einer Arraylist durch Variablen?
Erstmal mein Code, dann die Erklärungen.
Der Vollständigkeit halber ein größerer Ausschnitt der Klasse KontaktController:
boolean gefunden = true;
int durchgang = startseite;
int[] informationen = new int[2];
char[] zeichen = suchbegriff.toCharArray();
String zwischenspeicher = new String();
for(int j = 1; j <= 6; j++) {
switch (j){
case 1: zwischenspeicher = "sVorname"; break;
case 2: zwischenspeicher = "sNachname"; break;
case 3: zwischenspeicher = "sStrasse"; break;
case 4: zwischenspeicher = "sOrt"; break;
case 5: zwischenspeicher = "sPlz"; break;
case 6: zwischenspeicher = "sTelNummer"; break;
}
System.out.println(zwischenspeicher);
gefunden = true;
for (int i = 0; i < zeichen.length; i++) {
if (!kontaktArrayList.get(durchgang).zwischenspeicher.contains(String.valueOf(zeichen[i]))) {
gefunden = false;
}
}
Eigentlich geht es mir nur um die Zeile :
(!kontaktArrayList.get(durchgang).zwischenspeicher.contains(String.valueOf(zeichen[i])))
Ich möchte, mit der Variable "durchgang" auf ein bestimmtes Objekt der Klasse Kontakt zugegriffen wird, welche alle in der "kontaktArrayList" gespeichert sind. Es wird also ein bestimmtes Objekt zurückgegeben, von dem dann ein Attribut abgefragt werden soll. Welches das ist, wurde vorher in der Switch-Case Abfrage festgelegt.
Wenn ich direkt ein Attribut hinschreibe (z.B. [...] .get(durchgang).sVorname[...]), dann geht es. Ich müsste dann allerdings die innere For-Schleife sechs mal mit immer einem anderem Attribut nutzen, weshalb ich es lieber so machen würde, wie oben gezeigt. Die Fehlermeldung lautet "Cannot resolve symbol 'zwischenspeicher' ". Gibt es irgendeinen Trick oder muss man an bestimmten Stellen Klammern setzen, damit auf den Text von "zwischenspeicher" zugegriffen wird?
2 Antworten
Wie ich es verstehe, möchtest du im Grunde also nur in bestimmten Feldern eines Kontaktobjekts prüfen, ob sie die Zeichen enthalten, die auch im Suchbegriff zu finden sind.
Schreibe dir dazu einfach eine Methode:
private boolean wertEnthaeltZeichen(String wert, char[] zeichen) {
for (int i = 0; i < zeichen.length; ++i) {
if (wert.indexOf(zeichen[i]) == -1) {
return false;
}
}
}
und verwende sie dann für jedes Feld einzeln:
var kontakt = kontaktArrayList.get(startseite);
boolean gefunden = wertEnthaeltZeichen(kontakt.sVorname, zeichen);
// etc.
Diese Lösung ist viel einfacher zu durchschauen, ressourcensparender und kürzer.
Wobei es bei deiner Logik wohl auch ausreichen würde, immer nur das letzte Feld (sTelNummer) zu prüfen, immerhin überschreibst du deine Variable gefunden immer wieder.
Ebenso würde ich die Prüfung ernsthaft hinterfragen. Wenn du beispielsweise nach dem Wort test suchst, hast du bei dem Wort stets auch schon einen Fund. Ist das wirklich gewollt?
Gibt es irgendeinen Trick oder muss man an bestimmten Stellen Klammern setzen, damit auf den Text von "zwischenspeicher" zugegriffen wird?
Der Compiler sucht während der Kompilierungsphase in deiner Kontaktklasse nach einem Feld zwischenwert, welches es nicht gibt. Er wertet den String nicht aus, so wie du dir das vorstellst.
Mittels Introspection könnte man zur Laufzeit die Felder eines Objekts ermitteln. Für deinen Fall halte ich das aber dennoch für unnötig. Für sechs Anweisungen braucht man keine zusätzlichen Ressourcen verschleudern. Zudem gewinnst du dadurch nur Code-Zeilen hinzu.
PS.: Beschäftige dich einmal mit Kapselung, falls noch nicht getan. Einen direkten Zugriff auf Felder zu gewährleisten, würde ich erst einmal kritisch beäugen.
Genau. Da du deine Bezeicher allerdings alle in deutscher Sprache hältst, würde ich das auch einheitlich durchziehen (konkat.gibVorname).
dazu musstest du ein eval methode nutzen ob das bei java geht und ob das schlau ist lass ich mal dahingestellt sein , sieht eher nach faulheit oder schlechter architektur aus . aber vielleicht gibts ja jemanden der das normal findet. wie wäre es denn mit pointern zu arbeiten , leider hab ich keine ahnung wie java das so in seiner kapselung findet.
Danke für deine Antwort, ich werde mal nach diesen Stichworten googeln
@TechPech1984
Ich habe das hier gefunden:
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
Object result = engine.eval("4*5");
https://stackoverflow.com/questions/2605032/is-there-an-eval-function-in-java
Problem ist aber, dass IntelliJ mir keinen Import für den ScriptEngineManager und die ScriptEngine anzeigt.
Wenn ich dann "javax.script.AbstractScriptEngine" manuell importiere, kommt ein ewig langer Hinweis, von dem ich kaum was verstehe.
Ich denke, es wird darauf hinauslaufen, dass ich einfach die äußere For-Schleife sowie die Switch-Case Abfrage wegstreiche und die innere For-Schleife dann 6 mal mit dem jeweiligen Attribut einzeln (also 6x hintereinander) aufrufen muss.
Lasse solche Lösungen besser aus deinem Programm. Eine Engine muss Ausdrücke erst parsen und auswerten und wenn ungewollte Werte in die eval-Methode hineingeraten, werden gleich dazu noch Exceptions kreiert. Für ein einfach lösbares Problem würdest du also eine ressourcenfressende Architektur bauen, die dein Projekt nicht einfacher macht.
@regex9 Danke für den Hinweis. Ich habe jetzt, wie schon im vorherigen Kommentar geschrieben, die äußere For-Schleife und die Switch-Case abfrage entfernt und stattdessen die innere For-Schleife einfach 6 mal wiederholt.
@regex 9 ah hab grad gesehen, dass du noch eine ausführlichere Antwort geschrieben hast, die schaue ich mir mal an
Danke für deine Hilfe. Ich habe es jetzt so gemacht, wie von dir vorgeschlagen.
Also würde man dann lieber die Attribute in der Klasse Kontakt auf "private" setzen, dann für jedes Attribut eine Getter Methode schreiben und diese dann wo man sie braucht in der Klasse "Kontakt Controller" aufrufen?
Statt "kontakt.sVorname" dann "kontakt.getsVorname()"