Perché Java String non ha metodi di manipolazione di stringhe statiche?


17

Perché i progettisti Java non hanno creato versioni statiche dei metodi di manipolazione delle stringhe nella java.lang.Stringclasse? I seguenti metodi sono ciò a cui mi riferisco, ma la domanda può essere estesa anche ad altri metodi non statici nella classe.

concat(String)                        substring(int, int)
replace(char, char)                   toLowerCase()
replace(CharSequence, CharSequence)   toLowerCase(Locale)
replaceAll(String, String)            toString()
replaceFirst(String, String)          toUpperCase()
split(String)                         toUpperCase(Locale)
split(String, int)                    trim()
substring(int)

Avere solo versioni non statiche di questi metodi forza il controllo nullo esplicito ovunque un tale metodo debba essere chiamato. Ad esempio, la semplice chiamata example = example.trim()porterebbe a NullPointerException se String example = null. Quindi il programmatore deve eseguire il seguente controllo null sulla piastra di caldaia:

if (example != null)
    example = example.trim();
// OR:
example = (example==null) ? null : example.trim();
example = (example==null) ? null : example.substring(5);

Immagino che sarebbe stato molto più conveniente se Stringavessero avuto versioni statiche di questi metodi (forse anche esclusivamente ), che avrebbe preso la stringa di input come primo argomento:

example = String.trim(example);
example = String.replace(example, 'a', 'b');
example = String.substring(example, 5);

Ciò avrebbe portato a un codice più pulito scritto dai programmatori che si sarebbe automaticamente occupato di casi nulli semplicemente restituendo null, piuttosto che forzare i programmatori a gestire esplicitamente casi nulli. La restituzione di null ha senso per me poiché la manipolazione di una stringa null dovrebbe comportare una stringa null , non un errore.

Perché i progettisti Java non hanno pensato a questo quando hanno progettato la Stringclasse in Java 1 o Java 2 o addirittura hanno aggiunto tale funzionalità in una versione Java successiva?


17
Suggerirei di sostituire "Perché i progettisti Java non hanno pensato a X" con "Perché i progettisti Java hanno deciso contro X". Dai loro il merito di base di non essere ciechi rispetto all'opzione.
Avner Shahar-Kashtan,

5
nullè uno stato eccezionale e dovrebbe essere gestito in modo esplicito.
Codici InCos

2
@KonradMorawski: Personalmente trovo un grave abuso di metodi di estensione. Se hai un valore nullo, cosa stai facendo nel tentativo di chiamare metodi su di esso, confonderai tutti coloro che leggono quel codice. È una cattiva reimplementazione di un Maybe<T>tipo, immagino?
Phoshi,

1
Uno @Phoshi ha da tenere a mente che i metodi di estensione non sono metodi veri e propri, sono solo lo zucchero sintassi. Ma sono d'accordo che è controverso. Vorrei che C # / Java offrisse una sorta di sicurezza nulla sintattica integrata, come - diciamo - Kotlin. string name = employee?.personalData?.name. Proprio come una scorciatoia per tutti questi ripetitivi if (employee != null). Domanda SO correlata: stackoverflow.com/questions/1196031/…
Konrad Morawski

2
@ADTC Ehm, ti rendi conto che un programma non può prevedere in anticipo che un valore è nullo, giusto? - È necessario definire i contratti tra le interfacce in un modo che si può essere sicuri se un valore è permesso di essere nullo o meno. Il controllo null ovunque significa che hai un problema di progettazione del programma.
Uooo,

Risposte:


30

La restituzione di null ha senso per me poiché la manipolazione di una stringa null dovrebbe comportare una stringa null, non un errore

Bene, questa è la tua opinione. Altri potrebbero obiettare che le operazioni String su un oggetto null, che non contiene String, non hanno senso e quindi dovrebbero generare un'eccezione

Perché "designer Java" abbiano fatto o meno qualcosa è difficile da rispondere.

Esistono già librerie là fuori che possono eseguire operazioni String a rischio zero , ad esempio StringUtils di Apache Commons. Puoi usare quella o simili librerie se ne hai bisogno.


Aggiunta basata sui tuoi commenti

Leggendo i commenti, sembra che il vero problema che affronti sia che devi controllare nulltutto il tuo codice. Questo può essere un indicatore di una cattiva progettazione del programma senza contratti chiaramente definiti tra le interfacce. Potresti voler leggere Evitando le istruzioni “! = Null” in Java?


1
Grazie per il tuo feedback Immagino che la vera domanda sia: perché dobbiamo dipendere da una libreria esterna o da classi preparate in casa quando una tale funzionalità di base può far parte di Java standard?
ADTC

4
@ADTC poniamo la domanda al contrario: perché i "designer Java" dovrebbero includere qualcosa nel linguaggio, se ci sono già molte buone librerie là fuori, ben testate e documentate? Come definire una "caratteristica di base" si basa sull'opinione. Per la maggior parte di ogni progetto non è necessaria una libreria esterna per "Funzionalità di base" (unit test, derisione, data e ora, ...)? Non è un grosso problema, vero?
Uooo

Un modo di gestire i null è usare Guava Optional- code.google.com/p/guava-libraries/wiki/…
Konrad Morawski

10

IMO l'intero approccio "if arg is null return null" alla scrittura dei metodi aumenta inutilmente la complessità ciclomatica del tuo programma.

Le prime librerie Java utilizzavano l'approccio null null, ma i ragazzi JDK si sono sempre guardati bene da null con eccezioni.

Con il tempo, penso che quest'ultimo approccio sia diventato il chiaro vincitore.

Perché? Poiché i campi null infrangono molti principi oo. Semplicemente non puoi trattarli come membri di una classe polimorfica. Ciò significa che devi sempre codificare casi speciali per null, e quindi la tua complessità ciclomatica aumenta quando devi presumere che le cose possano essere null.

Per risolvere i tuoi problemi, considera di utilizzare il modello di oggetti null invece di fare affidamento su campi null.


2
Ma Stringnon è polimorfico, no? E come si usa il modello di oggetti null per un tipo già esistente come String?
svick,

La stringa non è polimorfica, no. Ma anche così vorresti sapere che puoi chiamare i metodi di istanza su qualsiasi riferimento di stringa che hai. Funziona con tutti i riferimenti non nulli. String ha già un oggetto null: la stringa vuota. Proprio come le liste hanno una lista vuota. Quindi chiediti perché la stringa vuota non è abbastanza nel tuo caso. Immagino che tu usi una stringa nulla per contrassegnare un caso speciale. Chiediti se puoi usare una bandiera separata per quel caso speciale.
Alexander Torstling,

@AlexanderTorstling: intper impostazione predefinita, un campo di tipo è zero anziché null. Concettualmente dovrebbe essere possibile avere un stringtipo il cui valore predefinito sarebbe una stringa vuota piuttosto che null[tale tipo potrebbe semanticamente essere Stringciò che intdeve Integer]. Il fatto che un non vuoto stringpossa contenere internamente un riferimento a un oggetto heap sarebbe un dettaglio di implementazione; non c'è motivo per cui non possa comportarsi semanticamente come una primitiva.
supercat il

@supercat: concordato. Penso che sarebbe stato meglio vietare valori nulli per le riforme se non fosse stato esplicitamente abilitato. Campi predefiniti non nulli e finali. Molti tipi hanno già oggetti comportamento nulli
Alexander Torstling il

@AlexanderTorstling: avere posizioni di archiviazione di tutti i tipi predefinite su all-byte-zero e fornire che i tipi di struttura possono essere assegnati tramite copia di tutti i byte, semplifica notevolmente un framework, ma praticamente implica che i tipi con semantica di riferimento mutabile devono essere predefiniti su nullo. Sarebbe stato utile, tuttavia, avere il supporto del framework per i tipi di valore che incapsulerebbero un singolo riferimento e si "incasserebbero" come - e potrebbe deselezionare da - quel tipo di riferimento .
supercat

3

Non dire questo è il motivo, ma tranne toString, tutti questi metodi sono facilmente incapsulati in una classe di supporto statica, mentre il contrario non è vero.

Vale a dire se vuoi Stings.toUpper (input stringa) il codice per questo è facile da scrivere, ma se vuoi instance.toUpper e tutto ciò che hai è String.toUpper, beh, è ​​impossibile ... a meno che non introducano metodi di estensione, che molto probabilmente non era nemmeno considerato al momento.


Buon punto, anche se più di un commento che una risposta. Ma anche considerato questo, perché dobbiamo dipendere da una libreria esterna o da classi preparate in casa quando una tale funzionalità di base può essere inserita in Java standard?
ADTC

2
A partire da ora, hai String.format(statico), ma non puoi farlo "something %s".format(id).
Konrad Morawski,

@adtc: perché non è una funzionalità di base del linguaggio farlo tramite una classe statica. A partire da questa premessa, ci sono molte ragioni per non farlo: codice / code float non necessari, funzionalità duplicata, costo di sviluppo / manutenzione.
jmoreno,

-2

In Java, quella stringa è un oggetto. Questa è una scelta di design.

I riferimenti agli oggetti possono essere nulli e nulli se non vi è alcun oggetto assegnato. Se si chiama tale oggetto, viene generata una NullPointerException. Questo è un comportamento oo standard.

I progettisti Java hanno fatto la scelta di avere stringhe come oggetto e avere quei metodi che generano eccezioni con puntatore null è ciò che ottieni se vuoi che le stringhe siano oggetti.

Perché i progettisti Java non hanno pensato a questo quando hanno progettato la classe String in Java 1 o Java 2 o addirittura hanno aggiunto tale funzionalità in una versione Java successiva?

Probabilmente ci hanno pensato e hanno scelto di incorporare l'oo-comportamento.


Posso sapere come sta creando metodi statici per occuparsi di casi nulli e non di comportamento OO ? Per essere chiari, non sto dicendo che lo sia, ma sto cercando di capire perché dici che la decisione di progettazione è quella di incorporare il comportamento OO.
ADTC

I metodi statici sono più simili alle funzioni. E per l'uso desiderato, non dovrebbero nemmeno far parte della classe di stringa, ma piuttosto far parte di una classe di utilità. Proprio come le funzioni di classe di matematica.
Pieter B,

4
Solo perché le stringhe sono oggetti non significa che la classe String non può avere metodi statici. E infatti ne ha già alcuni, ad es. String.format. (Lo stesso in C #, a proposito). Quindi, se questa è una scelta progettuale, non può venire esclusivamente dal fatto che le stringhe sono oggetti e non viene applicata in modo coerente.
Konrad Morawski,

@PieterB Non mi lamenterei se almeno tali metodi fossero forniti in una Stringsclasse di utilità, come se avessimo una Arraysclasse di utilità ( anche se capisco che è stata creata per pura necessità a causa delle matrici che sono una sorta di strano incrocio tra primitivi e oggetti: ) ) .. purché facesse parte di Java standard e non richiedesse dipendenze.
ADTC
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.