Programmation sous Android, la plupart des valeurs de texte sont attendues dans CharSequence
.
Pourquoi donc? Quel est l'avantage et quels sont les principaux impacts de l'utilisation CharSequence
excessive String
?
Quelles sont les principales différences et quels problèmes sont attendus lors de leur utilisation et de leur conversion de l'un à l'autre?
java
string
charsequence
e-satis
la source
la source
Réponses:
Les chaînes sont des CharSequences , vous pouvez donc simplement utiliser des chaînes et ne vous inquiétez pas. Android essaie simplement d'être utile en vous permettant de spécifier également d'autres objets CharSequence, comme StringBuffers.
la source
CharSequence
javadoc: cette interface ne raffine pas les contrats généraux des méthodesequals
ethashCode
. Le résultat de la comparaison de deux objets qui implémententCharSequence
est donc, en général, indéfini . Chaque objet peut être implémenté par une classe différente, et il n'y a aucune garantie que chaque classe sera capable de tester ses instances pour l'égalité avec celles de l'autre. Il est donc inapproprié d'utiliser desCharSequence
instances arbitraires comme éléments dans un ensemble ou comme clés dans une carte.CharSequence
était une mise à niveau dans JDK 1.4 pour introduire une interface commune à usage limité aux objets contenant des séquences de caractères. Certains de ces objets contiennent un autre état, il n'est donc pas logique de définirObject.equals
comme "contient la même séquence de caractères". NIOCharBuffer
, par exemple, expose uniquement les caractères entre sonposition
etlimit
comme leCharSequence
, bien qu'il puisse contenir de nombreux autres personnages.equals
/hashCode
surObject
en premier lieu ....Object
ou l' autreCharSequence
, aucune interface n'est requise pour fournir un équilibre entre les implémentations. Aucun deuxCollection
n'est requis pour assurer l'égalité entre l'Collection
interface, mais ils le peuvent s'ils le souhaitent. L'IMHOCharSequence
devrait être limité aux entrées et moins utilisé pour les types de retour.CharSequence
= interfaceString
= mise en œuvre concrèteCharSequence
est une interface .String
est une de ces classes, une implémentation concrète deCharSequence
.Tu as dit:
Il n'y a pas de conversion depuis
String
.String
objet est unCharSequence
.CharSequence
peut produire unString
. AppelleCharSequence::toString
. Si laCharSequence
se trouve être unString
, la méthode renvoie une référence à son propre objet.En d'autres termes, tout
String
est unCharSequence
, mais pas toutCharSequence
est unString
.Programmation vers une interface
Généralement, la programmation sur une interface est meilleure que la programmation sur des classes concrètes. Cela donne de la flexibilité, nous pouvons donc basculer entre les implémentations concrètes d'une interface particulière sans casser d'autres codes.
Lors du développement d'un API à utiliser par divers programmeurs dans diverses situations, écrivez votre code pour donner et prendre les interfaces les plus générales possibles. Cela donne au programmeur appelant la liberté d'utiliser diverses implémentations de cette interface, selon celle qui convient le mieux à son contexte particulier.
Par exemple, regardez le Java Collections Framework . Si votre API donne ou prend une collection ordonnée d'objets, déclarer vos méthodes que l' utilisation
List
plutôt queArrayList
,LinkedList
ou toute autre mise en œuvre 3ème partie deList
.Lorsque vous écrivez une petite méthode rapide et sale à utiliser uniquement par votre code à un endroit spécifique, par opposition à l'écriture d'une API à utiliser à plusieurs endroits, vous n'avez pas à vous soucier d'utiliser l'interface plus générale plutôt qu'un béton spécifique classe. Mais même dans ce cas, il est difficile d'utiliser l'interface la plus générale possible.
String
vous savez que vous avez un seul morceau de texte, entièrement en mémoire, et est immuable.CharSequence
, vous ne savez pas quelles pourraient être les particularités de l'implémentation concrète.L'
CharSequence
objet peut représenter un énorme morceau de texte, et a donc des implications de mémoire. Ou il peut y avoir de nombreux morceaux de texte suivis séparément qui devront être assemblés lorsque vous appeleztoString
, et ont donc des problèmes de performances. L'implémentation peut même récupérer du texte à partir d'un service distant et a donc des implications de latence.En général, vous ne vous convertirez pas d'avant en arrière. A
String
est unCharSequence
. Si votre méthode déclare qu'il faut unCharSequence
, le programmeur appelant peut passer unString
objet, ou peut passer quelque chose d'autre comme unStringBuffer
ouStringBuilder
. Le code de votre méthode utilisera simplement tout ce qui est passé, appelant l'une desCharSequence
méthodes.La conversion la plus proche serait si votre code reçoit un
CharSequence
et que vous savez que vous en avez besoinString
. Peut-être que vous interfacez avec de l'ancien code écrit enString
classe plutôt qu'en écrit sur l'CharSequence
interface. Ou peut-être que votre code fonctionnera intensément avec le texte, comme une boucle répétée ou une autre analyse. Dans ce cas, vous voulez prendre une seule fois les performances possibles, vous appeleztoString
donc à l'avance. Continuez ensuite votre travail en utilisant ce que vous savez être un seul morceau de texte entièrement en mémoire.Histoire tordue
Notez les commentaires faits sur la réponse acceptée . L'
CharSequence
interface a été adaptée aux structures de classe existantes, il y a donc quelques subtilités importantes (equals()
&hashCode()
). Remarquez les différentes versions de Java (1, 2, 4 et 5) marquées sur les classes / interfaces, ce qui a beaucoup bougé au fil des ans. Idéalement,CharSequence
il aurait été en place depuis le début, mais telle est la vie.Mon diagramme de classes ci-dessous peut vous aider à voir la grande image des types de chaînes en Java 7/8. Je ne sais pas si tous ces éléments sont présents dans Android, mais le contexte global peut toujours vous être utile.
la source
Je pense qu'il est préférable d'utiliser CharSequence. La raison en est que String implémente CharSequence, donc vous pouvez passer une String dans une CharSequence, CEPENDANT vous ne pouvez pas passer une CharSequence dans une String, car CharSequence n'implémente pas String. ÉGALEMENT, dans Android, la
EditText.getText()
méthode retourne un modifiable, qui implémente également CharSequence et peut être passé facilement en un, mais pas facilement en une chaîne. CharSequence s'occupe de tout!la source
charSequence.toString()
En général, l'utilisation d'une interface vous permet de varier la mise en œuvre avec un minimum de dommages collatéraux. Bien que java.lang.String soit très populaire, il peut être possible que dans certains contextes, vous souhaitiez utiliser une autre implémentation. En construisant l'API autour de CharSequences plutôt que de Strings, le code donne l'occasion de le faire.
la source
Il s'agit presque certainement de raisons de performances. Par exemple, imaginez un analyseur qui passe par un ByteBuffer de 500k contenant des chaînes.
Il existe 3 approches pour renvoyer le contenu de la chaîne:
Créez une chaîne [] au moment de l'analyse, un caractère à la fois. Cela prendra un temps considérable. Nous pouvons utiliser == au lieu de .equals pour comparer les références mises en cache.
Construisez un int [] avec des décalages au moment de l'analyse, puis construisez dynamiquement String quand un get () se produit. Chaque chaîne sera un nouvel objet, donc pas de mise en cache des valeurs retournées et en utilisant ==
Créez une CharSequence [] au moment de l'analyse. Puisqu'aucune nouvelle donnée n'est stockée (autre que les décalages dans le tampon d'octets), l'analyse est beaucoup plus faible que # 1. Au moment d'obtenir, nous n'avons pas besoin de construire une chaîne, donc les performances d'obtention sont égales à # 1 (bien mieux que # 2), car nous ne renvoyons qu'une référence à un objet existant.
En plus des gains de traitement que vous obtenez en utilisant CharSequence, vous réduisez également l'empreinte mémoire en ne dupliquant pas les données. Par exemple, si vous avez un tampon contenant 3 paragraphes de texte et que vous souhaitez renvoyer les 3 ou un seul paragraphe, vous avez besoin de 4 chaînes pour représenter cela. En utilisant CharSequence, vous n'avez besoin que d'un tampon avec les données et de 4 instances d'une implémentation CharSequence qui suit le début et la longueur.
la source
CharSequence
implémentation pour cela.CharSequence
est une interface - par définition, elle n'a aucun des détails d'implémentation dont vous discutez car elle n'a pas d'implémentation propre. AString
est l'une des nombreuses classes concrètes qui implémentent l'CharSequence
interface. Donc,String
c'est unCharSequence
. Vous pouvez comparer les détails des performances deString
vsStringBuffer
vsStringBuilder
, mais pasCharSequence
. Écrire «les gains de traitement que vous obtenez en utilisant CharSequence» n'a aucun sens.Un problème qui survient dans le code Android pratique est que leur comparaison avec CharSequence.equals est valide mais ne fonctionne pas nécessairement comme prévu.
La comparaison doit être faite par
la source
CharSequence
A
CharSequence
est une interface, pas une classe réelle. Une interface n'est qu'un ensemble de règles (méthodes) qu'une classe doit contenir si elle implémente l'interface. Dans Android aCharSequence
est un parapluie pour différents types de chaînes de texte. Voici quelques-uns des plus courants:String
(texte immuable sans étendue de style)StringBuilder
(texte modifiable sans étendue de style)SpannableString
(texte immuable avec des plages de style)SpannableStringBuilder
(texte modifiable avec des plages de style)(Vous pouvez en savoir plus sur les différences entre ces éléments ici .)
Si vous avez un
CharSequence
objet, il s'agit en fait d'un objet de l'une des classes qui implémententCharSequence
. Par exemple:L'avantage d'avoir un type générique général
CharSequence
est que vous pouvez gérer plusieurs types avec une seule méthode. Par exemple, si j'ai une méthode qui prend unCharSequence
comme paramètre, je pourrais passer unString
ou unSpannableStringBuilder
et il gérerait l'un ou l'autre.Chaîne
On pourrait dire que a
String
n'est qu'un typeCharSequence
. Cependant, contrairement àCharSequence
, il s'agit d'une classe réelle, vous pouvez donc en créer des objets. Vous pouvez donc faire ceci:mais vous ne pouvez pas faire ça:
Puisqu'il ne
CharSequence
s'agit que d'une liste de règlesString
conformes, vous pouvez le faire:Cela signifie que chaque fois qu'une méthode demande un
CharSequence
, il est bon de lui donner unString
.Cependant, l'inverse n'est pas vrai. Si la méthode prend un
String
paramètre, vous ne pouvez pas lui transmettre quelque chose qui n'est généralement connu que comme étant unCharSequence
, car il peut en fait s'agir d'unSpannableString
ou d'un autre type deCharSequence
.la source
CharSequence
est une interface et l'String
implémente. Vous pouvez instancier unString
mais vous ne pouvez pas le faireCharSequence
car il s'agit d'une interface. Vous pouvez trouver d'autres implémentationsCharSequence
dans le site officiel de Java.la source
CharSequence est une séquence lisible de valeurs char qui implémente String. il a 4 méthodes
Veuillez consulter la documentation Documentation CharSequence
la source
CharSequence
ne met pas en œuvreString
. L'inverse est vrai, cependant.