-2

In the below example, I am expecting equals() to return true:

public class flower {
    String flower;
    public flower (String flower) {
        this.flower = flower;
    }

    public static void main(String[] args) {
        flower one = new flower("Flower");
        boolean isSame = false;
        if(one.equals("Flower")) {
            isSame = true;
        }
        System.out.print(isSame);
    }
} 

However, the result I get is false... is it because I'm comparing an object with a String? I read the equals() method and is said to compare Strings with Objects. Why am I getting the result as false although they are the same?

Fuzz X
  • 47
  • 1
  • 2
  • 4
  • 1
    Look at the implementation of `equals()` which is defined in the Object class. –  May 27 '15 at 14:35
  • 3
    They are **not** the same. They're not even the same class. One has an attribute with a value that is *equal* to the other (but not the same). That is nowhere near close enough to satisfy `equals()`. – Kilian Foth May 27 '15 at 14:36
  • This is my car. (Imagine an Opel Corsa.) This is a Pirelli PT-1004 tyre. (Imagine a Pirelli PT-1004 tyre.) My car is ***most definitely not equal*** to the tyre, even though my car does in fact happen to be wearing Pirelli PT-1004 tyres. It won't be equal even if you steal 3 of my tyres and leave me with only one. It won't. Ever. Be equal. To a tyre. – Mike Nakis May 27 '15 at 15:25
  • 2
    why didn't you ask at Stack Overflow, are you [question blocked](http://meta.programmers.stackexchange.com/q/7020/31260) there? http://meta.stackexchange.com/a/129632/165773 – gnat May 27 '15 at 15:45
  • @MikeNakis: "It won't. Ever. Be equal. To a tyre." It will if your car and tire define `equals()` so they can be equal to each other. – user102008 May 27 '15 at 20:42

2 Answers2

7

The short answer: You need to override the implementation of equals() in your Flower (note: capital F) class. This will do something you like to do:

@Override
public boolean equals(Object o) {
    return (o instanceof Flower && ((Flower)o).flower.equals(flower)) ||
                (o instanceof String && o.equals(flower));
}

@Override
public int hashCode() {
    return flower.hashCode();
}

Overriding hashCode() together with equals() is good form: generally, the 'attributes' (e.g. fields) you pick for doing an equals() should be used in your hashCode() calculation too. In layman terms, they should 'agree' with each other.

The big/major/severe problem, as pointed out by practically everyone here I presume, is that equals() is meant to be symmetric:

It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.

And unfortunately for your Flower class, String.equals(Object) is defined as such:

The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object. (emphasis mine)

This means that no String will ever return true when you pass a Flower object to equals().

Sure, you can still go against the convention, but you'll likely run into bugs - minor or major - very soon when you learn more about the language, e.g. the Collection classes.

Therefore: avoid such comparisons with equals().

h.j.k.
  • 1,357
  • 2
  • 20
  • 30
1

As Killian says you are comparing an Flower object that contains an string attribute, to a string.

If you want to see if the Flower object's name attribute equals the string you need to check the actual strings.

one.name.equals("Flower")

thought this would be a really bad idea because a Flower object is not a string object, it merely contains a string object, so you aren't comparing like with like.

Cormac Mulhall
  • 1,197
  • 1
  • 8
  • 12