“black_fire”:
Só pra completar
String em java é um objeto, veja:
String s1 = "valor";
String s2 = "valor";
s1 não é igual a s2, pois são objetos diferentes.
So pra ser bem chato… se vc fizer isso, um teste com == nessas Strings vai retornar true!
Pra ficar mais pratico:
public class Teste {
public static void main(String[] args) {
String s1 = "valor";
String s2 = "valor";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
}
}
Vai imprimir true e true. Chocante, nao? 
Isto se deve a duas coisas: o pool de constantes que todo arquivo .class tem, e ao pool de Strings, que a classe String mantem internamente.
No primeiro (pool de constantes), todo valor literal (ou seja, todos aqueles que voce declarou direta e explicitamente no seu codigo) é colocado em um lugarzinho especial no arquivo .class. Como dá pra fazer Strings literais, assim como qualquer tipo primitivo, elas vao convenientemente parar no pool de constantes… 
Já o segundo, o pool de Strings, pode ser imaginado como um array de Strings estatico que reside dentro da classe java.lang.String, e é quase que totalmente invisível pro programador. É usado pros casos em que vc quer “fingir” que uma determinada String está no pool de constantes em algum lugar 
…mas calma, nao eh tao dificil assim… vou tentar explicar um pouco mais:
public class Teste {
public static void main(String[] args) {
String s1 = "valor";
String s2 = "valor";
String s3 = JOptionPane.showInputDialog("Digite 'valor':");
// "valor", tambem, mas veio de fora
System.out.println(s1 == s2); // true
System.out.println(s1.equals(s2)); // true
System.out.println(s1 == s3); // false
System.out.println(s1.equals(s3)); // true
s3 = s3.intern();
System.out.println(s1 == s3); // AHA! true
}
}