Strings are shared everywhere in a program, so Java makes them unchangeable to keep that sharing safe. Every method that seems to modify a string really returns a new one. This matters when you call s.toUpperCase() and forget to store the result, a classic bug. It is also why adding to a string inside a loop is slow, and why StringBuilder exists.