2012-03-19 14 views
8

Le differenze tra StringBuilder e StringBuffer in Java sono ben documentate e sono state anche touched upon in StackOverflow.Perché non avere StringBuilder e StringBuffer implementano un'interfaccia comune?

Fondamentalmente, StringBuilder è una copia non sincronizzata di StringBuffer, con praticamente la stessa interfaccia in quanto è stata concepita come una sostituzione drop-in più rapida per StringBuffer. La loro API è praticamente identica e in realtà sono sottoclassi della stessa inaccessibile classe nell'attuale JDK.

L'unica cosa che mi chiedo, quindi, è il motivo per cui non sono pubblicamente correlati. Avere entrambe le classi implementare un'interfaccia comune o anche avere StringBuffer come sottoclasse di StringBuilder avrebbe senso, consentendo l'esistenza di codice condiviso per entrambe le classi.

Quindi, perché questa separazione forzata? Era così che i programmatori non avrebbero inavvertitamente mescolato thread-safe con codice thread-safe? O era solo una supervisione del design che ora verrà ereditata fino alla fine dell'eternità?

EDIT:

di fare chiarezza: posso speculare sul perché le cose sono come questo, ma sto sperando di riferimenti concreti ad una decisione vera e propria, per esempio durante un processo JSR. Tutto ciò che potrebbe far luce su cosa, per me, è una situazione che causa occasionalmente una certa difficoltà.

EDIT 2:

Il fatto che entrambe le classi implementano Appendable completamente passato di mente. Probabilmente perché quella particolare interfaccia è inutile per la maggior parte degli scopi - può solo aggiungere un singolo carattere o un oggetto preparato e il gioco è fatto. Nella maggior parte dei casi non è più utile che entrambe le classi siano sottoclassi di Object.

EDIT 3:

Bene, qui è la spiegazione razionale per esattamente questa domanda da a semi-official source:

di valutazione da parte del team biblioteche:

E 'di design che StringBuffer e StringBuilder condividere nessun supertipo pubblico comune . Non sono pensati per essere alternativi: uno è un errore (StringBuffer) e l'altro (StringBuilder) è la sua sostituzione .

Chiaramente la mancanza di un supertipo comune può, in alcuni casi, rallentare la migrazione sperata di da StringBuffer a StringBuilder. Il rovescio della medaglia è che aggiungendo un supertipo comune, dovremmo prendere gli errori del nostro passato e archiviarli in un'interfaccia pubblica per stare con noi per tutto il tempo . Questo non rallenta semplicemente la migrazione: lo fa deragliare.

risposta

3

Non ho un riferimento JSR ma dal mio exp. Di seguito sono pochi motivi:

  • StringBuffer come sottoclasse di StringBuildernon è una buona idea per motivi di prestazioni. Per rendere sicuro il thread StringBuffer è necessario mascherare ogni chiamata a StringBuilder che è un sacco di spese generali.

  • Aggiungendo al punto di cui sopra, è possibile ottimizzare ulteriormente, se si ha accesso diretto sulle parti interne di una classe che è il motivo per cui Java aggiunto java.lang.concurrent sopra java.util.Collections.synchronized* apis. Come più accesso diretto offre più opzioni per l'ottimizzazione. Per suport questo punto Reference from the IBM blog

  • Ulteriore aggiunta al primo punto, mi Non che questa sia una svista di progettazione in quanto entrambe le classi sono final così sicuramente non desiderano queste classi da sottoclasse.

  • Per quanto riguarda le stesse interfacce, entrambe le classi implementano le stesse interfacce, ovvero Serializable, Appendable, CharSequence. Quindi sono rimpiazzi. L'unica cosa è che non implementano un'interfaccia comune ma piuttosto tre interfacce comuni. Il che ha senso, in quanto non c'è bisogno di avere un'interfaccia gonfia che tecnicamente sarà la somma delle interfacce attuali (Serializable, Appendable, CharSequence).

EDIT:

  • Per @MatthewFlaschen punto, che esistono API che sono stesso b/w StringBuffer e StringBuilder ma non in nessuna delle interfacce implementate. Questo è più a che fare con la retrocompatibilità. Si desidera aggiungere una nuova API ma l'interfaccia viene utilizzata da molte altre classi, pertanto la modifica di un'interfaccia potrebbe non essere possibile. Questa è una buona idea di decisione che i ragazzi di Java avrebbero potuto fare. Quindi non dirò che è un errore.

EDIT 2:

Nota a margine: Un'altra cosa da notare è che StringBuffer è stato introdotto nel 1.0 e StringBuilder nella 1.5. Quindi le apis che sono presenti in entrambe le classi ma non nelle interfacce vengono introdotte successivamente e non al momento della creazione di queste stesse classi.

+0

Esistono metodi, ad es. append (long) che si trovano in entrambe le classi ma nessuna delle interfacce. –

+0

Anche se penso che il modo in cui Vector e ArrayList estendano AbstractList, StringBuffer e StringBuilder potrebbero aver esteso una classe astratta simile. Non ho guardato l'ultima fonte, ma il StringBuilder sembrava essere un vero furto di StringBuffer meno la sincronizzazione. –

+0

@MatthewFlaschen append() è da Appendable. –

2

In realtà entrambi implementano Appendable.

Non sono d'accordo che questo è inutile.Nella mia esperienza, una grande parte dell'uso di StringBuilder/StringBuffer riguarda solo stringhe (che implementano CharSequence). Per il resto, è possibile chiamare String.valueOf prima di inoltrarlo.

Sarebbe conveniente se ci fosse un'altra interfaccia che avesse anche gli altri metodi come append(long). Ma non è essenziale.

Sarebbe ragionevole disporre di un'interfaccia comune. Hanno caratteristiche di performance e threading diverse, ma questo è vero e vero per molte interfacce nel JDK.

Ad esempio, in un elenco CopyOnWriteArrayList thread-safe basata su array (rende una nuova lista per ogni scrittura), mentre LinkedList è un elenco collegato non-thread-safe.

+0

Non hai risposto alla domanda, o anche solo qualche suggerimento sul perché potrebbe essere. – FriendlyGuy

+0

@MackieChan, non sono d'accordo. Ho detto "Sarebbe ragionevole avere un'interfaccia comune.", Che è un altro modo per dire "Sì, è una supervisione del design". –

+0

Onestamente, Appendable mi è sfuggito di mente, soprattutto perché aggiungo regolarmente i numeri e.t.c. nel mio codice. Non trovo davvero utile quella particolare interfaccia, perché ti obbliga a convertire tutto in una stringa in anticipo. Per non parlare del fatto che il contenuto esistente è immutabile ... – thkala

Problemi correlati