4

How can I check equality on a value of an enum? I tried the following, but it fails. WHy?

class enum Test {
    LETTER("1A");

    private String value;
    public Test(String value) {
        this.value = value;
    }

    @Override
    public void toString() {
        return value;
    }
}


String teststring = "1A".
Sysout(teststring.equals(Test.LETTER)); //false. Why???
membersound
  • 81,582
  • 193
  • 585
  • 1,120

5 Answers5

8

There are so much of other compiler errors in your code:

  • class enum Test should be enum Test.
  • An enum's constructor can only be private.
  • Return type of toString() method is void. That is not a valid override. Make the return type String.

I don't know whether these errors also persist in your original code, or it's just a mistake in your post.

Now coming to the concrete question. When you print an enum constant, the toString() method is automatically called on that. So, you would get 1A when you print Test.LETTER.

This is not true when passing Test.LETTER as argument to any method. You would have to call toString() explicitly. So, that should be:

System.out.println(teststring.equals(Test.LETTER.toString()));

Another way is to provide a method in your enum itself, which gets you an enum constant for a particular String value:

public static Test of(String str) {
    for (Test test: values()) {
        if (test.value.equals(str)) {
            return test;
        }
    }
    return null;
}

You can even cache the array returned by values() method, so that it not created again and again.

And then just compare the enum constant as:

String teststring = "1A";
System.out.println(Test.of(teststring) == Test.LETTER);
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • Thanks, of course these errors are not existent in my code, was just a (too) quick typo. – membersound Oct 25 '13 at 09:47
  • 1
    @RohitJain +1 But actually a potential problem can occur with the `of` function you provided. If you have `LETTER_B("1A"),LETTER("1A");` as enum constants, `Test.of(teststring) == Test.LETTER)` will return `false`. (even if this enum constans are actually stupid because they are basically the same) – Alexis C. Oct 25 '13 at 10:00
  • @ZouZou Well that's true, but I wouldn't consider those cases in comparison, as you already said, those enums would be stupid. Using `==` to compare enum constants are perfectly acceptable practice. See [this post](http://stackoverflow.com/q/1750435/1679863) – Rohit Jain Oct 25 '13 at 10:05
  • 1
    @Rohit Jain “Using == to compare enum constants are perfectly acceptable practice.”— that’s true, but you are comparing `String`s using `==`. But that’s a different problem, a method returning a single object cannot handle the case when two objects match the condition. – Holger Oct 25 '13 at 10:10
  • @Holger Oops. That was a blunder from my side. Thanks for pointing it out. – Rohit Jain Oct 25 '13 at 10:12
6

The comparison is returning false because you're comparing a String instance with an Enum instance.

@RohitJain already gave a great explanation about why the toString() method doesn't get called in your comparison in his answer, and how you should use it if it's what you want to do.

However, toString() shouldn't be used for comparison purposes, it should be overriden only to provide a custom String representation of the object.

You could compare the property you're really intereseted in comparing if you do this:

String teststring = "1A".
Sysout(teststring.equals(Test.LETTER.getValue())); // Will return true

Of course you should provide a getter for the value attribute or let it be visible to the operation doing the comparison.

You could also code a isEqual() method in your enum like this:

enum Test {
    LETTER("1A");

    private String value;
    private Test(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return value;
    }

    public boolean isEqual(String value) { 
        return this.value.equals(value);
    }
}

And just do Test.LETTER.isEqual(teststring) to do this comparison.

Or even a static getByValue(String value) method to get the enum instance for a given value:

enum Test { 
    ...
    public static Test getByValue(String val) { 
        for (Test c : values()) {
            if (c.value.equals(val)) {
                return c;
            }
        }
    } 
} 

Test x = Test.getByValue("1A"); // x == Test.LETTER
Community
  • 1
  • 1
Xavi López
  • 27,550
  • 11
  • 97
  • 161
1

Just do the check the following way and it will work

teststring.equals(Test.LETTER.toString())

Test.LETTER is an enum so it will never be equal to a String, but its value can be equal to a String so you have to check directly using the value of the enum.

user1983983
  • 4,793
  • 2
  • 15
  • 24
0

Because String's equals method is checking for the object received to be String as well. It should work if you try with Test.LETTER.toString().

Silviu Burcea
  • 5,103
  • 1
  • 29
  • 43
0

This will return false flag because of comparison between String object and ENUM instance.

If you do this:

String variable1 = "1A".
boolean flag = variable1.equals(Test.LETTER.value); 
system.out.println(flag);

This will return

True

all though

IN java .equals methods look like this

public final boolean equals(Object other) { 
    return this==other;
}

I always use == because it is null safe.

SSP
  • 2,650
  • 5
  • 31
  • 49
  • “IN java .equals and == are logically same” That’s completely wrong – Holger Oct 25 '13 at 09:46
  • Different classes have different implementations of `equals`. Since the question is about `String.equals` your statement remains wrong. And using `==` instead of `equals` when comparing `String`s is a bug. – Holger Oct 25 '13 at 09:58