Java String vergleichen mit Enum.name via == / !=

Hendoul

Commander
Registriert
Apr. 2008
Beiträge
2.049
Hi :)

Wollte grad einen simplen String mit einem Enum vergleichen und musste feststellen, dass es mit != nicht funktioniert

Java:
public enum MyEnum {
ABC
}

if("ABC" != MyEnum.ABC.name()) {
            ...
}

Warum trifft die if Bedingung trotzdem zu?
 
Ah ne ich habs, das sind ja dann 2 Strings und die werden dann auf Objekt-Referenz Gleichheit geprüft wenn man == verwendet.
 
  • Gefällt mir
Reaktionen: madmax2010
Ich weiß, du hast dir deine Frage selbst schon beantwortet.
Da du aber offensichtlich noch Anfänger bist wollte ich noch ein paar Dinge über Enumerations loswerden, die ich selbst gerne früher schon gewusst hätte.

Hier erstmal der Code.

Java:
public enum Month {
    
    // ===================================================================
    // {[> Identifiers
    // ===============
    JANUARY(1, "January"),
    FEBRUARY(2, "February"),
    MARCH(3, "March"),
    APRIL(4, "April"),
    MAY(5, "May"),
    JUNE(6, "June"),
    JULY(7, "July"),
    AUGUST(8, "August"),
    SEPTEMBER(9, "Septembe"),
    OCTOBER(10, "October"),
    NOVEMBER(11, "November"),
    DECEMBER(12, "December");
    
    
    
    // ===================================================================
    // {[> Attributes
    // ==============
    private final String name;
    private final int order;
    
    
    // ===================================================================
    // {[> Initializers and Constructors
    // =================================
    Month(int order, String name) {
        this.name = name;
        this.order = order;
    }
    
    
    
    // ===================================================================
    // {[> Public Static Methods
    // =========================
    public static Month byName(String name) {
        
        for (Month m : Month.values()) {
            
            if (m.name.equalsIgnoreCase(name)) {
                return m;
            }
        }
        
        throw new NoSuchElementException("No month found for name: " + name);
    }
    
    public static Month byOrder(int order) {
        
        for (Month m : Month.values()) {
            
            if (m.order == order) {
                return m;
            }
        }
        
        throw new NoSuchElementException("No month found for order: " + order);
    }
    
    
    
    // ===================================================================
    // {[> Public Methods
    // ==================
    public String getName() {
        return name;
    }
    
    public int getOrder() {
        return order;
    }
}

Java:
public class Example {
    
    public static void main(String[] args) {
        
        String userInput = "January";
        
        Month m = Month.byName(userInput);
        
        if (m == Month.JANUARY) {
            System.out.println("A new year begins...");
        }
    }
}

Nun ein paar Anmerkungen dazu.

Zum Ersten werden Identifier in Enumerations grundsätzlich, genauso wie Konstanten, groß geschrieben.

Zweitens finde ich persönlich es nicht gut, die name() Methode von Enumerations zu benutzen. Weshalb? Weil du auf diese Weise den Wert einer Konstante an ihren Namen koppelst. In meinem Beispiel sind Wert und Name unabhängig von einander und du kannst beides getrennt umbennen, falls notwendig.
 
  • Gefällt mir
Reaktionen: BeBur
Hendoul schrieb:
Warum trifft die if Bedingung trotzdem zu?
Strings werden in Java interniert. Das trifft auch auf enum-Konstruktoren zu. Die gezeigte Bedingung sollte nicht zutreffen (also nicht wahr sein).

Beispiel:
Java:
package myenums;

public enum EA {
    enum1
}

package myenums;

public enum EB {
    enum1
}

package myenums;

public class ETest {
    public static void main(String[] args) {
        System.out.println("enum1" == EA.enum1.name()); // both interned/pooled
        System.out.println("enum1" == EB.enum1.name()); // both interned/pooled
        System.out.println(EA.enum1.name() == EB.enum1.name()); // both interned/pooled
        System.out.println(EA.enum1.name() != new String(EB.enum1.name())); // only one interned, the other new referenced
    }
}

Führt man diesen Code aus, sollte 4x true ausgegeben werden.

Der Grund ist einfach, == prüft auf referentielle Gleichheit (Identität), nicht auf inhaltliche Gleichheit.

Da Enum-Namen in einen Pool gelegt werden, handelt es sich um dasselbe Objekt.

!= ist dementsprechend einfach der invertierte Wert.

a.equals(b) kann überprüfen, ob die zwei Zeichenketten a und b inhaltlich gleich sind, das heißt, stellenweise nur identische Zeichen besitzen.

Ich hoffe, ich konnte dir ein bisschen helfen. Des Weiteren ist folgende Antwort interessant: https://www.thecodeteacher.com/question/95159/Are-enum-names-interned-in-Java?
 
Zurück
Oben