In this gist, i will try to explain you what is the main differences between known string comparison techniques and where to use them.
This is the main equality operator in Java. To summarize it, this method compares the left and right hands references to eachother and returns boolean. This means this operator returns true only if left and right variable both point at the same Object in the memory. As in most of the class comparisons, this operators is discouraged to use if you're not really intented to check if two variables point to same object.
This method is defined by Object class and every class you customly made has it. But this methods doesnt makes an truly right comparison if its not overriden by the class of the object. Since java core classes overrides it, this method is encouraged to use in String comparison.
This method compares a variable to the given regex. Even though it returns true for some cases like "hello".matches("hello"), this method's main object is to match a String to the given regex. So even though the two strings is equal to each other like; "hello+".matches("hello+"), since they had a regex character in them, this comprasion will return false. So you must use this method only when you know what is regex and you need it.
This method compares a string to a given string and returns a value according to the lexicographical(alphabetical) difference of the strings. Meaning it will return 0 if the strings are the same, negative or positive value if they are not. This method can be used in alphabetical ordering. This method is discouraged to use in String comparison because it will throw NullPointerException if the value given to the method is null.
Now lets see these methods in action and how they behave compared to eachother.
String a = "hello";
String b = "hello";
String c = "hell";
c += "o";
String d = "hi";
System.out.println("==:");
System.out.println(a == b); // => true
System.out.println(a == c); // => false
System.out.println(a == d); // => false
System.out.println("equals:");
System.out.println(a.equals(b)); // => true
System.out.println(a.equals(c)); // => true
System.out.println(a.equals(d)); // => false
System.out.println("compareTo:");
System.out.println(a.compareTo(b)); // => 0
System.out.println(a.compareTo(c)); // => 0
System.out.println(a.compareTo(d)); // => -4
Only thing that needs explanation in this sample is "a == b" returning true and "a == c" returning false. Given that a, b are defined by themselves rather than making a statement like "String b = a;", it may be thought that 'a' and 'b' doesn't point to the same object. This is not true since java automatically checks in the compile time if string constants are assigned to same value, and at the start assigns them to the same object, making a little bit optimization (String Pool). Since strings are immutable, this method works without having any sync problems. Therefor "a == b" returns true. But since "String c" gets its value assigned to "hello" in runtime, "a == c" returns false. Keep in mind also if String c would be assigned as "String c = "hell" + "o"" in the code, "a == c" would also return true since java also concatenates these kind of string additions in compile time.
Knowing that matches and compareTo are simply the same for straight string comparison, i will use equals to differentiate matches from equals and compareTo.
String x = "hello";
String y = "hello";
System.out.println(x.matches(y)); // => true
System.out.println(x.equals(y)); // => true
But would it be the same case for every string rather than "hello"? After asking this question to ourselves, lets try this code and run it;
String x = "hello+";
String y = "hello+";
System.out.println(x.matches(y)); // => false
System.out.println(x.equals(y)); // => true
Now we see the difference between these methods easily.
I have done some tests in String Pool. There was a unclear case related to your code examples. Could you explain this.
If i move this line
String s2 = "hello";
to the first line, the result will be false exactly like your example.