Pourquoi les concepteurs Java n'ont-ils pas créé des versions statiques des méthodes de manipulation de chaînes dans la java.lang.String
classe? Je fais référence aux méthodes suivantes, mais la question peut également être étendue à d'autres méthodes non statiques de la 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)
Le fait de n'avoir que des versions non statiques de ces méthodes force une vérification nulle explicite partout où une telle méthode doit être appelée. Par exemple, un simple appel example = example.trim()
entraînerait NullPointerException if String example = null
. Le programmeur doit donc effectuer la vérification nulle du passe-partout suivante:
if (example != null)
example = example.trim();
// OR:
example = (example==null) ? null : example.trim();
example = (example==null) ? null : example.substring(5);
J'imagine qu'il aurait été beaucoup plus pratique d' String
avoir eu des versions statiques de ces méthodes (peut-être même exclusivement ), qui prendraient la chaîne d'entrée comme premier argument:
example = String.trim(example);
example = String.replace(example, 'a', 'b');
example = String.substring(example, 5);
Cela aurait conduit à un code plus propre écrit par les programmeurs qui aurait automatiquement pris en charge les cas nuls en renvoyant simplement null, plutôt que de forcer les programmeurs à gérer explicitement les cas nuls. Le retour de null a du sens pour moi, car la manipulation d'une chaîne nulle devrait entraîner une chaîne nulle , pas une erreur.
Pourquoi les concepteurs Java n'ont-ils pas pensé à cela lorsqu'ils ont conçu la String
classe en Java 1 ou Java 2, ou même ajouté une telle fonctionnalité dans une version Java ultérieure?
la source
null
est un état exceptionnel et doit être traité explicitement.Maybe<T>
type, je suppose?string name = employee?.personalData?.name
. Tout comme un raccourci pour tous cesif (employee != null)
s répétitifs . Question SO connexe: stackoverflow.com/questions/1196031/…Réponses:
Eh bien, c'est votre opinion. D'autres peuvent argumenter que les opérations String sur un objet nul, qui ne contient pas de chaîne, n'ont aucun sens et devraient donc lever une exception
Il est difficile de savoir pourquoi les «concepteurs Java» ont fait ou non quelque chose.
Il existe déjà des bibliothèques qui peuvent effectuer des opérations String sans danger, par exemple StringUtils d'Apache Commons. Vous pouvez utiliser cela ou des bibliothèques similaires si vous en avez besoin.
Ajout basé sur vos commentaires
En lisant les commentaires, il semble que le vrai problème auquel vous êtes confronté est que vous devez vérifier
null
partout votre code. Cela peut être un indicateur d'une mauvaise conception de programme sans contrats clairement définis entre les interfaces. Vous voudrez peut-être lire Éviter les instructions «! = Null» en Java?la source
Optional
- code.google.com/p/guava-libraries/wiki/…IMO l'approche "if arg is null return null" des méthodes d'écriture augmente inutilement la complexité cyclomatique de votre programme.
Les premières bibliothèques Java utilisaient l'approche return null, mais les gars JDK se gardaient toujours de null avec des exceptions.
Avec le temps, je pense que cette dernière approche est apparue comme le gagnant clair.
Pourquoi? Puisque les champs nuls cassent beaucoup de principes oo. Vous ne pouvez tout simplement pas les traiter comme des membres d'une classe polymorphe. Cela signifie que vous devez toujours coder des cas spéciaux pour null, et donc votre complexité cyclomatique monte en flèche lorsque vous devez supposer que les choses peuvent être nulles.
Afin de résoudre vos problèmes, envisagez d'utiliser le modèle d'objet nul au lieu de vous fier aux champs nuls.
la source
String
n'est-ce pas polymorphe, non? Et comment utilisez-vous le modèle d'objet nul pour un type déjà existant comme String?int
défaut est zéro plutôt quenull
. Conceptuellement, il devrait être possible d'avoir unstring
type dont la valeur par défaut serait une chaîne vide plutôt quenull
[un tel type pourrait sémantiquement être versString
ce quiint
doit êtreInteger
]. Le fait qu'un non-videstring
contienne en interne une référence à un objet tas serait un détail d'implémentation; il n'y a aucune raison qu'il ne puisse pas se comporter sémantiquement comme une primitive.Cela ne veut pas dire que c'est la raison, mais à l'exception de toString, toutes ces méthodes sont facilement encapsulées dans une classe d'assistance statique, tandis que l'inverse n'est pas vrai.
C'est-à-dire si vous voulez Stings.toUpper (entrée de chaîne), le code pour cela est facile à écrire, mais si vous voulez instance.toUpper et tout ce que vous avez est String.toUpper, eh bien, c'est impossible ... à moins qu'ils n'introduisent des méthodes d'extension, ce qui n'était probablement pas envisagé à l'époque.
la source
String.format
(statique), mais vous ne pouvez pas"something %s".format(id)
.En java, cette chaîne est un objet. C'est un choix de conception.
Les références d'objets peuvent être nulles et sont nulles si aucun objet ne leur est affecté. Si vous appelez un tel objet, une NullPointerException est levée. C'est un oo-comportement standard.
Les concepteurs Java ont fait le choix d'avoir des chaînes comme objet et de disposer de ces méthodes pour lancer des exceptions de pointeur nul, c'est ce que vous obtenez si vous voulez que les chaînes soient des objets.
Ils y ont probablement réfléchi et ont choisi d'incorporer un oo-comportement.
la source
String.format
. (Pareil en C #, d'ailleurs). Donc, si c'est un choix de conception, cela ne peut pas venir uniquement du fait que les chaînes sont des objets, et ce n'est pas appliqué de manière cohérente.Strings
classe utilitaire, comme nous avons laArrays
classe utilitaire ( bien que je comprenne qu'elle a été créée par pure nécessité en raison des tableaux étant une sorte de croisement étrange entre les primitives et les objets: ) ) .. tant qu'il faisait partie de Java standard et ne nécessitait pas de dépendances.