String is immutable means that you cannot change the object itself, but you can change the reference to the object. When you called
s1 = "abc";
s1 = "def";
, you are actually changing the reference of s1 to a new object created by the String literal "def".
S1 is only the reference to the Object , it is not the actual object

Try this way
s1="abc";
s1.toUpperCase();
System.out.println(s1);
Output will be still
abc
Since s1.toUpperCase()
instead of changing the contents of String s1 it creates a new Object with Upper Case Contents but since we haven't catch the returning variable that is why output is still same
Now try using
s1="abc";
s1=s1.toUpperCase();
System.out.println(s1);
Now output
ABC