En programmant 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 de CharSequence
sur String
?
Quelles sont les principales différences et quels problèmes sont attendus lors de leur utilisation et de la conversion de l'un à l'autre?
Les chaînes sont des séquences de caractères , vous pouvez donc simplement utiliser des chaînes sans vous inquiéter. Android tente simplement de vous aider en vous permettant de spécifier d'autres objets CharSequence, tels que StringBuffers.
Ce diagramme de classes peut vous aider à avoir une vue d’ensemble des types de chaînes dans Java 7/8. Je ne sais pas si tout cela est présent dans Android, mais le contexte général peut encore vous être utile.
Notez également les commentaires faits sur le réponse acceptée . L'interface CharSequence
a été intégrée aux structures de classes existantes, de sorte qu'il existe certaines subtilités importantes (equals()
& hashCode()
). Notez les différentes versions de Java (1, 2, 4 & 5) balisées sur les classes/interfaces, ce qui a provoqué beaucoup de déséquilibre au fil des ans. Idéalement, CharSequence
aurait été en place depuis le début, mais telle est la vie.
Je crois qu'il est préférable d'utiliser CharSequence. La raison en est que String implémente CharSequence. Par conséquent, vous pouvez passer d'une chaîne à une CharSequence. CEPENDANT, vous ne pouvez pas transmettre une CharSequence à une chaîne, car CharSequence ne l'implémente pas. AUSSI, dans Android, la méthode EditText.getText()
renvoie un Editable, qui implémente également CharSequence et peut être passé facilement en un, mais pas facilement en une chaîne. CharSequence gère tout!
En général, l’utilisation d’une interface vous permet de varier l’implémentation avec un minimum de dommages collatéraux. Bien que Java.lang.String soit très populaire, il est possible que, dans certains contextes, on veuille utiliser une autre implémentation. En construisant l'API autour de CharSequences plutôt que de chaînes, le code donne l'occasion de le faire.
Ce sont presque certainement des raisons de performance. Par exemple, imaginez un analyseur qui parcourt un ByteBuffer de 500 Ko contenant des chaînes.
Il existe 3 approches pour renvoyer le contenu de la chaîne:
Construisez 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 en cache.
Construisez un int [] avec des décalages au moment de l'analyse, puis construisez dynamiquement String lorsqu'un get () se produit. Chaque chaîne sera un nouvel objet, aussi aucune mise en cache ne retournera de valeur et utiliser ==
Construire un CharSequence [] au moment de l'analyse. Etant donné qu'aucune nouvelle donnée n'est stockée (à l'exception des décalages dans la mémoire tampon d'octets), l'analyse est beaucoup plus basse que # 1. Au moment de la lecture, il n'est pas nécessaire de créer une chaîne. Par conséquent, les performances sont égales à # 1 (bien mieux que n ° 2), car nous ne renvoyons qu'une référence à un objet existant.
En plus des gains de traitement obtenus avec CharSequence, vous réduisez également l'encombrement de la mémoire en ne dupliquant pas les données. Par exemple, si vous avez un tampon contenant 3 paragraphes de texte et que vous voulez renvoyer tous les 3 ou un seul paragraphe, vous avez besoin de 4 chaînes pour le représenter. Avec CharSequence, vous n’avez besoin que d’un tampon avec les données et de 4 instances d’une implémentation CharSequence permettant de suivre le début et la longueur.
Un problème qui se pose dans le code pratique Android est que leur comparaison avec CharSequence.equals est valide mais ne fonctionne pas nécessairement comme prévu.
EditText t = (EditText )getView(R.id.myEditText); // Contains "OK"
Boolean isFalse = t.getText().equals("OK"); // will always return false.
La comparaison doit être faite par
("OK").contentEquals(t.GetText());
A CharSequence
est une interface et non une classe réelle. Une interface est simplement un ensemble de règles (méthodes) qu'une classe doit contenir si elle implémente l'interface. Dans Android, CharSequence
est un parapluie pour divers types de chaînes de texte. Voici quelques-uns des plus communs:
String
(texte immuable sans portée de style)StringBuilder
(texte modifiable sans étendue de style)SpannableString
(texte immuable avec une étendue de style)SpannableStringBuilder
(texte modifiable avec des portées de style)(Vous pouvez en savoir plus sur les différences entre ces ici .)
Si vous avez un objet CharSequence
, il s'agit en fait d'un objet de l'une des classes qui implémentent CharSequence
. Par exemple:
CharSequence myString = "hello";
CharSequence mySpannableStringBuilder = new SpannableStringBuilder();
L'avantage d'avoir un type de parapluie général tel que CharSequence
est que vous pouvez gérer plusieurs types avec une seule méthode. Par exemple, si j’ai une méthode qui prend un paramètre CharSequence
, je pourrais passer un String
ou un SpannableStringBuilder
et l’un ou l’autre des cas.
public int getLength(CharSequence text) {
return text.length();
}
Vous pourriez dire qu'un String
n'est qu'un type de CharSequence
. Cependant, contrairement à CharSequence
, c'est une classe réelle, vous pouvez donc en faire des objets. Pour que vous puissiez faire ceci:
String myString = new String();
mais vous ne pouvez pas faire ceci:
CharSequence myCharSequence = new CharSequence(); // error: 'CharSequence is abstract; cannot be instantiated
Comme CharSequence
est juste une liste de règles auxquelles String
se conforme, vous pouvez faire ceci:
CharSequence myString = new String();
Cela signifie que chaque fois qu'une méthode demande un CharSequence
, il est correct de lui donner un String
.
String myString = "hello";
getLength(myString); // OK
// ...
public int getLength(CharSequence text) {
return text.length();
}
Cependant, le contraire n'est pas vrai. Si la méthode prend un paramètre String
, vous ne pouvez pas lui transmettre quelque chose qui est généralement connu comme étant un CharSequence
, car il peut s'agir en réalité d'un SpannableString
ou d'un autre type de CharSequence
.
CharSequence myString = "hello";
getLength(myString); // error
// ...
public int getLength(String text) {
return text.length();
}
CharSequence
est une interface et String
l'implémente. Vous pouvez instancier une String
mais vous ne pouvez pas le faire pour CharSequence
puisqu'il s'agit d'une interface. Vous pouvez trouver d'autres implémentations dans CharSequence
sur le site officiel Java.