como o renan disse, o lance é o seguinte, em Java, existe um pool de strings q a JVM mantém... bem, vejamos, strings são objetos usados pelo programa todo, e consomem memória afuzel... quando tu faz isso:
String s1 = "portal java";
vc esta instanciando um novo objeto string e colocando ele no pool... para q, quando outra referencia de string receber o valor "portal java", faça uma referencia pra esse mesmo objeto (isto é pra nao disperdiçar memória, ele usa o mesmo objeto pra instancias diferentes), ex:
String s2 = "portal java";
System.out.println( s1 == s2 );
esse código imprime "true"... pq, quando eu digo pra ele atribuir "portal java" a referencia s2, ele procura no pool por uma string com esse valor, e atribuir....... É POR ISSO Q STRINGS SÃO IMUTÁVEIS........ imagina se agora, eu mudo o valor "portal java" de s2 para "eu amo o portal java", ... s1 passaria a referenciar o mesmo objeto??? Não, se isso acontecesse, seria um baita erro... bem, e se eu fizer isso aqui:
String s3 = new String( "portal java" );
ele vai estar criando um OUTRO objeto string, e não vai usar o q esta no pool... pq? pq vc esta dizendo explicitamente q será uma string nova, usando o operador new...
há diferenças na prática? Eu diria q não... strings são imutáveis.. :)