The differences between StringBuilder
and StringBuffer
in Java are well documented and have been touched upon in StackOverflow as well.
Basically, StringBuilder
is a non-synchronized copy of StringBuffer
, with pretty much the same interface since it was intended as a faster drop-in replacement for StringBuffer
. Their API is practically identical and they are actually subclasses of the same inaccessible abstract class in the current JDK.
The one thing I wonder about, therefore, is why they are not publicly related. Having both classes implement a common interface or even having StringBuffer
as a subclass of StringBuilder
would make sense, allowing the existence of shared code for both classes.
So why this forced separation? Was it so that programmers would not inadvertently mix thread-safe with thread-unsafe code? Or was it just a design oversight that will now be inherited to the end of eternity?
EDIT:
To make things clear: I can speculate on why things are like this, but I am hoping for concrete references to an actual decision, e.g. during a JSR process. Anything that would shed some light on what, to me, is a situation that causes a certain amount of difficulty occasionally.
EDIT 2:
The fact that both classes implement Appendable
completely slipped my mind. Probably because that particular interface is useless for most purposes - it can only append a single character or a prepared object and that's it. In most cases it's no more useful than both classes being subclasses of Object
.
EDIT 3:
Well, here is the rationale for exactly this question from a semi-official source:
Evaluation by the libraries team:
It is by design that StringBuffer and StringBuilder share no common public supertype. They are not intended to be alternatives: one is a mistake (StringBuffer), and the other (StringBuilder) is its replacement.
Clearly the lack of a common supertype can, in some cases, slow the hoped-for migration from StringBuffer to StringBuilder. The flip side is that by adding a common supertype, we'd be taking the errors of our past and enshrining them in a public interface to be with us for all time. This doesn't merely slow the migration: it derails it.
StringBuilder is not synchronized so that it is not thread-safe. By not being synchronized, the performance of StringBuilder can be better than StringBuffer. If we are working in a single-threaded environment, using StringBuilder instead of StringBuffer may result in increased performance.
In contrast to Java's String class, StringBuffer and StringBuilder are both mutable classes. The StringBuilder class and the StringBuffer class have the same API. The sole distinction is that whereas StringBuilder is neither synchronized nor thread-safe, StringBuffer is.
If a string can change and will be accessed from multiple threads, use a StringBuffer because StringBuffer is synchronous, so you have thread-safety. If you don't want thread-safety than you can also go with StringBuilder class as it is not synchronized.
So Java has provided StringBuffer and StringBuilder classes that should be used for String manipulation. StringBuffer and StringBuilder are mutable objects in Java. They provide append(), insert(), delete(), and substring() methods for String manipulation.
I dont have a JSR reference but from my exp. below are the few reasons:
StringBuffer
as a subclass of StringBuilder
is not a good idea for performance reasons. As to make StringBuffer
thread safe you have to mask every call to StringBuilder
which is lot of overhead.
Adding to above point, you can further optimize, if you have direct access over the internals of a class that is the reason why Java added java.lang.concurrent
over java.util.Collections.synchronized*
apis. As more direct access gives more options for optimization. To suport this point Reference from the IBM blog
Further adding to first point, I don't think this is a design oversight as both the classes are final
so definitely they dont want these classes to be subclassed.
Regarding same interfaces, both classes implement the same interfaces i.e Serializable, Appendable, CharSequence
. So they are drop-in replacement. The only thing is that they are not implement one common interface but instead three common interfaces. Which make sense, as there is no need to have one bloated interface which technically gonna be sum of current interfaces(Serializable, Appendable, CharSequence
).
EDIT:
StringBuffer
and StringBuilder
but not in any of the implemented interfaces. This is more to do with backward compatibility. You want to add a new api but the interface is being used by many other classes, so changing an interface may not be feasible soln. That is a well thought of decision that Java guys might have made. So I wont say its a mistake.EDIT 2:
SIDE NOTE: Another thing to note is that StringBuffer
was introduced in 1.0 and StringBuilder
in 1.5. So the apis which are there in both classes but not in interfaces are introduced later and not at the time of creating of these too classes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With