Java String läßt sich nicht vergleichen (ist evtl kein String)

Knito

Commander
Registriert
Sep. 2010
Beiträge
2.291
Moin, ich bin leider in java nicht zuhause und habe hier ein kleines Problem:
ich bekomm "match.getName()" nicht so umgewandelt, dass es zu einem positiven Vergleich führt.

match.getName() gibt immer "test" zurück unten in der Ausgabe. Ich möchte den Wert an farbname übergeben um ihn zu vergleichen.
Es scheint auch zu funktionieren, da die ausgabe_b unten den richtigen Wert ausgibt.
Trotzdem wird das if ignoriert.

Ich bin für alle Gedanken dankbar.

Java:
String rezept = "";

//String farbname = new String("test"); <-- GEHT
//String farbname = new String(String.valueOf(match.getName())); <-- GEHT NICHT

String farbname = new String(match.getName()); <-- GEHT NICHT

String vergleich = new String("test");

if (farbname.equals(vergleich)) {

    rezept = new String("inhalt");

}

((TextView) (view.findViewById(R.id.ausgabe_a))).setText("a"+rezept+"a"); <- SOLLTE inhalt sein, ist es aber nicht, nur aa
((TextView) (view.findViewById(R.id.ausgabe_b))).setText("a"+farbname+"a"); <-- IST IMMER atesta
((TextView) (view.findViewById(R.id.ausgabe_c))).setText("a"+vergleich+"a"); <-- IST IMMER atesta
 
Ich bin vielleicht etwas verwirrt, aber warum schreibst du nicht einfach:
Code:
string farbname = match.getName(); // vorausgesetzt hier wird ein String zurück gegeben!
string vergleich = "test";

Brauchst du hier das String Objekt? DU kannst halt das Objekt nicht mit der Referenz vergleichen.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Knito
Hi,

vielleicht mal so versuchen:

Code:
if (farbname.equalsIgnoreCase(vergleich))

Gruß
Bob
 
  • Gefällt mir
Reaktionen: Knito
Hab beides probiert. Ändert leider nichts.
Ergänzung ()

Brauchst du hier das String Objekt? DU kannst halt das Objekt nicht mit der Referenz vergleichen.
Ich bin mir nicht sicher. Ich benötige den Wert den match.getName() ausgibt.
farbname
gibt den richtigen Wert aus: "test" , identisch zu vergleich mit "test".

((TextView) (view.findViewById(R.id.ausgabe_b))).setText("a"+farbname+"a"); <-- IST IMMER atesta
((TextView) (view.findViewById(R.id.ausgabe_c))).setText("a"+vergleich+"a"); <-- IST IMMER atesta
 
Zuletzt bearbeitet:
Hi,

Dann würde ich eine Schleife, die jeden Buchstaben von den beiden Strings vergleicht, erstellen und schauen bei welcher Stelle er einen Fehler wirft.

Gruß
Bob
 
  • Gefällt mir
Reaktionen: Knito
Wie ist das Objekt "match" aufgebaut?
Ist das Property "name" wirklich ein String bzw. liefert "getName()" ein String Objekt?

So sieht die equals Methode aus:
Code:
public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

Wie wäre es mit debuggen?
Setz mal einen Haltepunkt in der equals-Methode bei "int i = 0;" und schau dir v1 und v2 an.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Knito
Also wir sollten schon wissen was match macht.

Also wird return "Test" zurück gegeben oder new String("test") oder oder oder
 
  • Gefällt mir
Reaktionen: Knito
Das Objekt kommt aus einer Lib in die ich keinen Einblick habe. Die Sache ist verzwickt, die Daten kommen von einem Bluetooth Gerät und mir fehlen leider die Skills um es auf Android zu debuggen.

Ich hatte gehofft ich könnte aus dem Ergebnis von match.getName() einfach einen String machen und den vergleichen, da kommen mir aber langsam Zweifel.
 
Warum in Gottes Namen erzeugt man auch Strings mit "new String"?????

Damit hebelst du das ganze Stringpooling aus! Referenzvergleich (==) funktionieren so natürlich auch nicht mehr, da du jedesmal ein neues Stringobjekt erzeugst, anstelle den gleichen immer wieder zu verwenden. Somit verfügen beide Instanzen (die lexikalisch gleich sind) über unterschiedliche Speicheradressen und der Vergleich geht natürlich in die Hose!

Du hast 2 Möglichkeiten:
  1. Lass den Blödsinn mit new beim Erzeugen von Strings (dann geht auch der Vergleich mit "==" wieder)
  2. Verwende zum Vergleich kein Referenzvergleich sondern einen inhaltlichen Vergleich mittels der equals Methode der Klasse String

greetz
hroessler
 
  • Gefällt mir
Reaktionen: Knito
Du brauchst doch in der IDE einfach nur mit der Maus über "getName()" von "match.getName()" drüber gehen, drücke linke STRG-Taste, dann siehst du schon mal, was zurück gegeben wird.
 
  • Gefällt mir
Reaktionen: Knito
Strg-links sagt
match:
match = item.match

get.Name():
public String get.Name()

okay, ich lass das new mal.
 
Zuletzt bearbeitet:
ich würde dir empfehlen:

if (!Strings.isNullOrEmpty(match.getName)) {

String farbname = match.getName()
}

und dann vergleich per equals
 
  • Gefällt mir
Reaktionen: Knito
hroessler schrieb:
Lass den Blödsinn mit new beim Erzeugen von Strings (dann geht auch der Vergleich mit "==" wieder)

Was zum!? Wenn zwei Strings inhaltlich gleich sein sollen, dann wird immer mit equals verglichen. String Pooling hin oder her. Das ist eine implementation Detail der Oracle JVM. Es gibt keine Garantie, dass andere Implementierungen, wie Android, das genauso handhaben. Abgesehen davon funktioniert das bestenfalls für statische Strings. Sich auf die Gleichheit der Pointer zu verlassen ist ein Rezept für Bugs.


@Knito
Du könntest versuchen die Variablen im Vergleich im Log auszugeben um zu sehen warum sie nicht gleich sind.
 
  • Gefällt mir
Reaktionen: Knito
Mir fällt auf, dass es sich um einen primitiven Datentyp handelt, also um ein kleines string (mit kleinem s)
 
  • Gefällt mir
Reaktionen: Knito
wahli schrieb:
Mir fällt auf, dass es sich um einen primitiven Datentyp handelt, also um ein kleines string (mit kleinem s)
denke er hat sicher vertippt oder ?
 
  • Gefällt mir
Reaktionen: Knito
Ja, er hat sich bestimmt vertippt, weil es kein kleines "string" gibt :D

Dann debuggen und schauen, was die equals Methode macht.
 
  • Gefällt mir
Reaktionen: Knito
Simon#G schrieb:
Was zum!? Wenn zwei Strings inhaltlich gleich sein sollen, dann wird immer mit equals verglichen. String Pooling hin oder her. Das ist eine implementation Detail der Oracle JVM. Es gibt keine Garantie, dass andere Implementierungen, wie Android, das genauso handhaben. Abgesehen davon funktioniert das bestenfalls für statische Strings. Sich auf die Gleichheit der Pointer zu verlassen ist ein Rezept für Bugs.
Da Strings eh unmutable sind ist das überhaupt kein Problem. Es wird IMMER ein neuer String erzeugt wenn du einen bestehenden änderst (sofern dieser noch nicht gepoolt ist). Zudem ist der Referenzvergleich flotter. Der Vergleich bei Strings mittels equals ist (bei sauberem Verwenden des Stringpooling) pure Rechenzeitverschwendung!

PS. Zeig mir die implementierung irgendeiner JVM, die kein oder ein anderes Stringpooling implementiert. Ich habe noch keine gesehen, in 20 Jahren Berufserfahrung.

greetz
hroessler
 
Zuletzt bearbeitet von einem Moderator:
  • Gefällt mir
Reaktionen: Knito
ja vertippt, sry.

Java:
String rezept = "";

//String farbname = new String("test");
//String farbname = new String(match.getName());
//String farbname = String.valueOf(match.getName());

String farbname = match.getName();

String vergleich = "test";

//if (vergleich == farbname) {
//if (vergleich.compareTo(farbname) == 0) {

if (farbname.equals(vergleich)) {

    rezept = "inhalt";

}

((TextView) (view.findViewById(R.id.ausgabe_a))).setText("a"+rezept+"a");
((TextView) (view.findViewById(R.id.ausgabe_b))).setText("a"+farbname+"a");
((TextView) (view.findViewById(R.id.ausgabe_c))).setText("a"+vergleich+"a");

Mein log ist quasi die ausgabe_a,b,c. Dort sind die werte identisch. Das Script läuft auf Android und wird gefüttert von Bluetooth, da reicht mein Wissen nicht um das im Studio zu simulieren. Dh. ich bau jedesmal eine APK die auf dem Handy installiert wird und koppel dann das Bluetooth und beobachte die Werte in der Ausgabe.

Ohne "new" oder mit == ändert leider nichts.

Output:
aa
atesta
atesta
 
Zuletzt bearbeitet:
Farbname.equals(match.getName()) wird immer korrekt sein. Such woanders den Fehler. String vergleiche sind absolutes Core Zeug. Dann sind die Strings nicht gleich, darauf kannst du dich verlassen.

Strings werden immer mit equals verglichen... das sollte man wissen. Alles andere ist fehlerbehaftet
 
  • Gefällt mir
Reaktionen: Knito
hroessler schrieb:
PS. Zeig mir die implementierung irgendeiner JVM, die kein oder ein anderes Stringpooling implementiert. Ich habe noch keine gesehen, in 20 Jahren Berufserfahrung.

Mit Java 7 hat Oracle den String Pooling Algorithmus verändert. Zum Bessern zwar, aber dennoch: Es gibt was das angeht keine Garantien.

PS: OpenJDK macht in der equals Funktion direkt zu allererst den Pointervergleich. Durch die Pooling-Trickserei hast du also nix gewonnen außer potenzielle Probleme.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Knito
Zurück
Oben