Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why not have StringBuilder and StringBuffer implement a common interface? [closed]

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.

like image 965
thkala Avatar asked Mar 19 '12 03:03

thkala


People also ask

Why StringBuilder is not synchronized?

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.

Do StringBuffer and StringBuilder have the same API?

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.

When should we use StringBuffer instead of StringBuilder and why?

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.

Has provided StringBuffer and StringBuilder class that should be used for?

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.


1 Answers

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:

  • To @MatthewFlaschen point, that there are apis which are same b/w 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.

like image 148
havexz Avatar answered Oct 17 '22 02:10

havexz