9

Today I was reminded of a valuable lesson... Never compare strings with == in java... Just spent like 30 minutes wondering why my string that I was getting from a browser parameter wasn't equalling the value I was checking for...

Apparently when I get a value from a requestParameter in spring, despite being a string it doesn't get a hashCode for some reason, or at least it got a hashcode of 0, so my strings weren't comparing because of that...

Comments
  • 7
    It’s classic beginner java mistake.
  • 3
    in Java this rule applies to ALL the objects. == only compares if you have THE SAME object, i.e. the same reference to an object. This operator is not to be used to check whether objects are alike each other and it has nothing to do with hashes.

    In order to compare objects use .equals() method. Always.

    You can only use == reliably for primitives. Nothing more. And String is not a primitive
  • 1
    I don't think hashcodes are even relevant in this case
  • 2
    @netikras Yes. But they could’ve make exception for strings… Like C#. And by the way, if you think string and String are the same thing in c#, you are wrong :)
  • 3
    @NoToJavaScript Well, maybe if Java was released 5 years later and could learn from Java's mistakes... oh wait.
  • 1
    @gronostaj On paper, Java is doing it the RIGHT way. It is just a need syntax sugar. I wonder to what IL “==” between strings compiles in .Net
  • 1
    @NoToJavaScript in c# we compare everything with == because it compares the value by default.
  • 0
    @superuser False. Objects are compared by reference by default. But you can override “==” operator.
  • 1
    @NoToJavaScript But they did :)

    jshell> "hello" == "hello"
    $1 ==> true

    Except this rule only works with static const strings, i.e. hardcoded ones.

    jshell> new StringBuilder("H").append("ello").toString() == "Hello"
    $3 ==> false

    jshell> "H" + "ello" == "Hello" // compiler treats this as "Hello" == "Hello"
    $4 ==> true

    And I find it perfectly sensible. Since everything is an object in Java, even Strings, it makes perfect sense to have Strings act like other objects.
  • 1
    @netikras Yes. strings are exceptions! Exactly as I wrote. Not even exceptions, they just have == already overridden.

    Edit : Ah ok, you were talking about Java. Didn't know about constants tho !
  • 0
    @NoToJavaScript as for C# I do remember strings being treated as primitives and Strings - as objects. Does my memory serves me well? And I _think_ String has a method to convert it to a primitive. Boy it was so long ago since I last touched C# :D
  • 0
    @NoToJavaScript oops yeah, lol.
    I believe that the obj == null came in my mind and i wrote this, i cant find any other logical explanation.
  • 1
    @netikras A bit different, here is an exellent post (short)

    https://blog.paranoidcoding.com/201...
  • 1
    @NoToJavaScript good read, thanks :) So basically string is the primitive (the value itself) while String is just a type that by default is defined to be a wrapper/boxer for string primitives?
  • 1
    @netikras At least it is my understanding !
  • 0
    @netikras it works for small Integer (object, not primitive) values too, and interned strings, possibly others, because they're eagerly deduplicated in memory for performance. Takes a lot of load off the garbage collector.

    == is risky in *many* languages unless you know exactly what it does.
  • 1
    @vane one that I should know considering I've made it in the past XD, my java is rusty apparently
  • 0
    @gaurdianaq yeah I would probably make same mistake Today since I haven’t touched java for couple of years.

    Those glitches makes switching between programming languages pain in the ass.
  • 0
    @netikras I'd just add Enums to the list of things you can compare with ==

    If you check the equals() it just does == and I find it more readable then Equals for Enums
  • 1
    @Hazarth You're right, == also works for enums, since compiler treats them as static final values as well.
  • 2
    @netikras yep! And it even has an advantage because its null safe (because you can == null to an enum and get false)

    Unlike .equals()!

    So both
    Enum.VAL == variable
    And
    variable == Enum.VAL
    Will work

    But
    variable.equals(Enum.VAL) can throw a NPE. And honestly I don't like how Enum.VAL.equals(variable) reads because it doesn't come of natural

    It's like saying
    "5 is the number of people in this room?"
    Instead of
    "In this room, are there 5 people?"
  • 1
    @Hazarth I agree!

    Though there was a reason why I had ruled out == as dangerous for enums. But I cannot remember what was the reason :D Could be it was project speciffic......
Add Comment