Différence exacte entre CharSequence et String en java [dupliquer]

cette question a déjà une réponse ici:

j'ai lu ce post précédent . Est-ce que quelqu'un peut dire quelle est la différence exacte entre CharSequence et chaîne de caractères, autre que le fait que String instruments CharSequence et que String est une séquence de caractère? Par exemple:

CharSequence obj = "hello";
String str = "hello";
System.out.println("output is : " + obj + "  " + str);

que se passe-t-il lorsque "hello" est affecté à obj et de nouveau à str ?

90
demandé sur Community 2012-07-04 11:00:36

8 réponses

différences

il existe plusieurs classes qui implémentent l'interface CharSequence en plus String . Parmi ceux-ci sont

  • StringBuilder pour les séquences de caractères de longueur variable pouvant être modifiées
  • CharBuffer pour les séquences de caractères de faible niveau de longueur fixe qui peut être modifié

toute méthode qui accepte un CharSequence peut fonctionner sur tous ces également bien. Toute méthode qui n'accepte qu'un String devra être convertie. Donc, utiliser CharSequence comme un type d'argument dans tous les endroits où vous ne vous souciez pas des internes est prudent. Cependant, vous devez utiliser String comme type de retour si vous retournez réellement un String , parce que cela évite les conversions possibles des valeurs retournées si l'appelant méthode ne nécessite effectivement un String .

notez également que les cartes doivent utiliser String comme type de clé, et non CharSequence , car les clés de carte ne doivent pas changer. En d'autres termes, parfois la nature immuable de String est essentielle.

code spécifique snippet

comme pour le code que vous avez collé: compilez simplement cela, et jetez un oeil au bytecode JVM en utilisant javap -v . Là, vous remarquerez que les deux obj et str sont des références au même objet constant. Comme un String est immuable, ce genre de partage est correct.

l'opérateur + de String est compilé en invocations de divers appels StringBuilder.append . C'est donc l'équivalent de

System.out.println(
  (new StringBuilder())
  .append("output is : ")
  .append((Object)obj)
  .append(" ")
  .append(str)
  .toString()
)

je dois avouer que je suis un peu surpris que mon compilateur javac 1.6.0_33 compile le + obj en utilisant StringBuilder.append(Object) au lieu de StringBuilder.append(CharSequence) . Le premier implique probablement un appel à la méthode toString() de l'objet, alors que cette dernière devrait être possible d'une manière plus efficace. D'un autre côté, String.toString() renvoie simplement le String lui-même, donc il y a peu de pénalité là. Ainsi StringBuilder.append(String) pourrait être plus efficace par environ une méthode invocation.

89
répondu MvG 2015-05-18 22:44:47

tl; dr

L'un est une interface ( CharSequence ) tandis que l'autre est une mise en œuvre concrète de cette interface ( String ).

CharSequence animal = "cat"  // `String` object presented as the interface `CharSequence`.

comme une interface, normalement le CharSequence serait plus communément vu que String , mais une certaine histoire tordue a abouti à l'interface étant défini années après la mise en œuvre. Ainsi, dans les APIs plus âgés, nous souvent voir String alors que dans les API plus récentes nous avons tendance à voir CharSequence utilisé pour définir les arguments et les types de retour.

détails

de nos jours, nous savons que généralement un API/framework devrait se concentrer sur l'exportation des interfaces principalement et des classes concrètes de façon secondaire. Mais nous n'avons pas toujours compris cette leçon.

la classe String est arrivée en premier à Java. Ce n'est que plus tard qu'ils ont placé une interface face à l'avant, CharSequence .

Histoire Tordue

un peu d'histoire pourrait aider à comprendre.

à ses débuts, Java a été précipité sur le marché un peu en avance sur son temps, en raison de la manie Internet/Web animant l'industrie. Certaines bibliothèques n'étaient pas aussi réfléchies qu'elles auraient dû l'être. La manipulation des ficelles était l'un de ces domaines.

aussi, Java a été l'un des premiers non-universitaires orientés vers la production la Programmation Orientée Objet (POO) environnements. La seule mise en œuvre réussie de l'OOP dans le monde réel a été quelques versions limitées de SmallTalk , puis Objective-C avec NeXTSTEP / OpenStep . De nombreux enseignements pratiques n'ont donc pas encore été tirés.

Java a commencé avec le String classe et StringBuffer classe. Mais ces deux classes n'étaient pas liées, ni par héritage ni par interface. Plus tard, L'équipe Java a reconnu qu'il aurait dû y avoir un lien unificateur entre les implémentations liées aux chaînes de caractères pour les rendre interchangeables. En Java 4, l'équipe a ajouté l'interface CharSequence et a mis en œuvre rétroactivement cette interface sur le tampon de chaîne de caractères, ainsi que l'ajout d'une autre implémentation. CharBuffer . Plus tard dans Java 5 ils ont ajouté StringBuilder , fondamentalement une version non synchronisée et donc un peu plus rapide de StringBuffer .

donc ces cours axés sur les cordes sont un peu un gâchis, et un peu confus à apprendre. De nombreuses bibliothèques et interfaces ont été construites pour prendre et retourner des objets String . De nos jours, de telles bibliothèques devraient généralement être construites pour CharSequence . Mais (a) String semble toujours dominer l'espace mental, et (b) il peut y avoir quelques problèmes techniques subtils lors du mélange des différentes implémentations CharSequence . Avec la vision 20/20 du recul, nous pouvons voir que toutes ces ficelles auraient pu être mieux gérées, mais nous y voilà.

idéalement Java aurait commencé avec une interface et / ou une superclasse qui serait utilisé dans de nombreux endroits où nous utilisons maintenant String , tout comme nous utilisons le Collection ou List interfaces à la place des ArrayList ou LinkedList implémentations.

De L'Interface Et Des Catégories De

la principale différence par rapport à CharSequence est qu'il s'agit d'une interface , et non d'une implémentation . Cela signifie que vous ne pouvez pas instancier directement un CharSequence . Vous instanciez plutôt l'un des les classes qui implémentent cette interface.

par exemple, nous avons ici x qui ressemble à un CharSequence mais en dessous est en fait un StringBuilder objet.

CharSequence x = new StringBuilder( "dog" );

cela devient moins évident quand on utilise une chaîne littérale. Gardez à l'esprit que lorsque vous voyez du code source avec juste des guillemets autour des caractères, le compilateur le traduit en un objet String.

CharSequence y = "cat";  // Looks like a CharSequence but is actually a String instance.

il y a des différences subtiles entre "cat" et new String("cat") , comme on l'a vu dans cette autre Question , mais elles ne sont pas pertinentes ici.

Schéma De Classe

ce diagramme de classe peut vous aider à vous orienter. J'ai noté la version de Java dans laquelle ils ont semblé démontrer combien de changement a jailli à travers ces classes et interfaces.

diagram showing the various string-related classes and interfaces as of Java 8

String Raw literals

une version future de Java peut obtenir la nouvelle fonctionnalité de les lignes brutes littérales . Cela rendrait l'écriture de chaînes de code intégrées telles que SQL plus commode. Voir JEP 326 .

ce JEP propose un nouveau type de littéral, une chaîne brute littéral, qui met de côté à la fois Java escapes et Java line terminator spécifications, pour fournir le caractère séquences qui, dans de nombreuses circonstances, sont plus lisibles et maintenables que la chaîne traditionnelle littérale existante.

Pour plus de détails, voir ce post , et de voir ce post par Goetz, Raw littéraux de chaîne-où nous sommes, comment nous sommes arrivés ici .

77
répondu Basil Bourque 2018-08-01 17:26:16

CharSequence est un contrat ( interface ), et String est un mise en œuvre du présent Contrat.

public final class String extends Object 
    implements Serializable, Comparable<String>, CharSequence

le documentation pour CharSequence est:

Un CharSequence est lisible une séquence de char valeurs. Cette interface offre un accès uniforme et en lecture seule à de nombreux types de caractères séquence. Une valeur char représente caractère dans la Base Plan multilingue (BMP) ou un substitut. Se référer au caractère Unicode Représentation pour plus de détails.

20
répondu Francisco Spaeth 2015-07-01 17:15:58

autre que le fait que String implémente CharSequence et que String est une séquence de caractères.

plusieurs choses se produisent dans votre code:

CharSequence obj = "hello";

Qui crée un String littérales "hello" , qui est un String objet. Étant un String , qui met en œuvre CharSequence , il est également un CharSequence . (vous pouvez lire ce message sur le codage à l'interface par exemple).

la ligne suivante:

String str = "hello";

est un peu plus complexe. String littéraux en Java sont détenus dans une piscine (internés) de sorte que le "hello" sur cette ligne est le même objet (identité) comme le "hello" sur la première ligne. Par conséquent, cette ligne assigne seulement le même String littéral à str .

à ce point, les deux obj et str sont des références à la String littéral "hello" et sont donc equals , == et ils sont à la fois un String et un CharSequence .

je vous suggère de tester ce code, en montrant en action ce que je viens d'écrire:

public static void main(String[] args) {
    CharSequence obj = "hello";
    String str = "hello";
    System.out.println("Type of obj: " + obj.getClass().getSimpleName());
    System.out.println("Type of str: " + str.getClass().getSimpleName());
    System.out.println("Value of obj: " + obj);
    System.out.println("Value of str: " + str);
    System.out.println("Is obj a String? " + (obj instanceof String));
    System.out.println("Is obj a CharSequence? " + (obj instanceof CharSequence));
    System.out.println("Is str a String? " + (str instanceof String));
    System.out.println("Is str a CharSequence? " + (str instanceof CharSequence));
    System.out.println("Is \"hello\" a String? " + ("hello" instanceof String));
    System.out.println("Is \"hello\" a CharSequence? " + ("hello" instanceof CharSequence));
    System.out.println("str.equals(obj)? " + str.equals(obj));
    System.out.println("(str == obj)? " + (str == obj));
}
11
répondu assylias 2017-05-23 11:47:36

je connais une sorte d'évidence, mais CharSequence est une interface tandis que String est une classe de béton :)

de java.lang.String est une implémentation de cette interface...

2
répondu Mark Bramnik 2012-07-04 07:03:01

Consider UTF-8. En UTF-8, les points de code Unicode sont construits à partir d'un ou plusieurs octets. Une classe encapsulant un tableau de octets UTF-8 peut implémenter L'interface CharSequence mais n'est pas une chaîne de caractères. Vous ne pouvez certainement pas passer un tableau de octets UTF-8 où une chaîne de caractères est attendue, mais vous pouvez certainement passer une classe de wrapper UTF-8 qui implémente CharSequence lorsque le contrat est assoupli pour permettre une CharSequence. Sur mon projet, je développe une classe appelée CBTF8Field (Compressed Binary Transfer) Format-huit bits) pour fournir la compression de données pour xml et am à la recherche d'utiliser L'interface CharSequence pour mettre en œuvre des conversions à partir de tableaux d'octets CBTF8 vers/à partir de tableaux de caractères (UTF-16) et tableaux d'octets (UTF-8).

la raison pour laquelle je suis venu ici était d'obtenir une compréhension complète du contrat subséquent.

2
répondu Patrick Campbell 2013-09-20 19:10:16

de L'API Java de CharSequence :

Un CharSequence est lisible une séquence de caractères. Cette interface offre un accès uniforme, en lecture seule, à de nombreux types différents de séquences de caractères.

cette interface est ensuite utilisée par String , CharBuffer et StringBuffer pour garder la cohérence pour tous les noms de méthode.

1
répondu Andreas Johansson 2012-07-04 07:06:45

dans charSequence vous n'avez pas de méthodes très utiles qui sont disponibles pour la chaîne. Si vous ne voulez pas regarder dans la documentation, type: obj. et Str.

et voir quelles méthodes votre compilateur vous offre. C'est la différence fondamentale pour moi.

0
répondu Doszi89 2012-07-04 07:10:07