To complement the other answers I will tell you that there is no rule to compare the equality of a chain, both the method
.equals() and the operator == are fully valid, the difference depends on what you want to compare or what is really your intention when wanting to compare two objects
String , (by reference or by value).
Chains are Objects like any other but there are great and subtle differences that separate them from the rest of Objects, first of all you can initialize a chain in these two ways.
String usandoLiteral = "Mi literal"; // Por medio de un literal
String usandoNew = new String("Con operador new"); // Utilizando el operador clasico new
In both cases an object is being created, the absence of the operator
new in the first example is only a shortcut (so it looks more natural).
Now we have to understand how Java manages the strings, in Java there is the String Pool, this is a memory space reserved for storing the strings, an application usually makes a strong use of Strings and only these can occupy up to a 40% of the memory in runtime and many of these String's are repeated for example 'a' 'in' 'the' 'etc. To optimize this, Java collects all these strings as literals in a JVM location and reuses repeated literals to optimize the use of memory, so if you store the literal "carlos" in two variables, Java will reuse this literal.
For this reason, if you declare the following variables
String and initialize them with the same literal. (remember that you are creating two Objects)
String nombre = "carlos";
String nombre2 = "carlos";
The comparison with the operator == will return true, because the String Pool recycles the literal "carlos" and therefore they are the same reference, therefore it is completely valid to make the comparison.
Boolean sonIguales = nombre == nombre2; // sonIguales tiene el valor true
The String Pool only recycles and stores literals, this means that if you create a string in the following way
String nombre3 = new String("carlos");
Not being initialized with a literal java will not store it in the String Pool nor will there be recycling therefore it will be eliminated by the Garbage Collector, if this is so then the following comparison will result in false.
Boolean esIgualAlTercero = nombre == nombre3; // esIgualAlTercero tiene el valor false.
This is the reason why when you make the comparison with the operator == sometimes it will give you true and sometimes it will give you false even though you compare the same value in the chain.
The .equals method you use when you want to compare the string by value or character by character, is a sure way to make the string comparison since remember that as in the first example we technically made a comparison by value with the operator = = due to the peculiarity of the String Pool.
An additional note in case you ask, if initializing a string by literal value is stored in the String Pool that happens when I change the string?
Well that's another point, the chains in Java are immutable, this means that you can not modify their value for example adding more characters to a String value and Java does not provide any API to modify a String directly. (however, Java provides an API to do it indirectly)
For example, if I want to add the last name to my variable (name) what I can do is re assign to the variable (name) a new string that I'll build it by concatenating the original value with the last name of this way.
nombre = nombre + " lucero";
This what it does is create a new value "carlos lucero" and assign this value to the string name.
Now what happens if I now compare 'name' with a new variable that contains the same value as 'name' but assigned as literal?
String nombreCompleto = "carlos lucero";
Boolean esNombreCompletoIgual = nombreCompleto == nombre; // recuerda que nombre ahora tiene el valor "carlos lucero"
Because the variable (name) was re assigned to a new value that was not created by means of a literal because now the variable (name) is no longer in the String Pool, therefore your reference is not recycled and the comparison with the variable (fullName) that was created by means of a literal will result in False.
Finally Java provides an API to solve the problem of immutability of the chains, this API is exposed by the class