This will never change, much code has been made with this premise.
In general, it is not detrimental to performance in ways that are worthwhile. Java, like some other languages, is not intended to have the best performance possible, but the most appropriate performance for most situations. Certainly loses in some things and wins in others.
Competition
One reason for this is competition. It is very difficult to handle mutable objects when access can be done in different threads. This is very important today. Treating changeable string concurrently is poor from a performance standpoint because it requires locking. That alone has a cost. Worse, this cost can be paid even if you are not doing anything competing. It is done "just in case." You can even optimize this, but it's very complicated.
Protection
Imagine that you get a file name to open, then the file name is changed by another thread and then the operation that was valid is no longer. What is the solution? You would have to lock the string during the entire operation. But it may be that other parts of the code that need to handle this string can not do anything anymore, have to wait. It can release soon, or take hours, days, It is infeasible. What is the solution? Copy the content, so you have a new object. But it may be that you've copied something that will not even be changed by another thread . So the copy made was a waste . In most cases this is what happens.
Changeable strings play the responsibility of protecting text for anyone to read. Most of the time this protection is not necessary, but you pay the price anyway, because you have no way of knowing when it will be necessary or not, except in extremely simple code, which is not the case with language libraries. These copies never know if there is a competition problem or not.
Protection in the right place
Unchanging Strings put the cost of protecting the text to anyone who changes its value. Writings occur very little in a code. It is better to pay this price.
If you know you have a case that will make several changes use StringBuilder
and then convert to String
( related ). This is a changeable string and was not intended for indiscriminate use, it should be used at a specific point and never shared between threads .
Hashing
It makes it difficult or even unfeasible to use them as structure keys like HashMap
(If the hash code changes easily, you need to reorganize the buckets structure at any time.)
Other reasons
Switchable strings are more insecure (improper access), make caching difficult, reuse ( interning by Flyweight ) and compile-time optimizations. Reflection gets a lot more complicated.