462 Stimmen

CharSequence VS String in Java?

Bei der Programmierung in Android werden die meisten Textwerte in CharSequence .

Warum ist das so? Was ist der Nutzen und was sind die Hauptauswirkungen der Verwendung CharSequence über String ?

Welches sind die Hauptunterschiede und welche Probleme sind bei der Verwendung und der Umstellung von einem zum anderen zu erwarten?

1 Stimmen

363voto

Zarkonnen Punkte 21817

Zeichenketten sind CharSequences Sie können also einfach Strings verwenden und sich keine Sorgen machen. Android versucht lediglich, hilfreich zu sein, indem es Ihnen erlaubt, auch andere CharSequence-Objekte, wie StringBuffers, anzugeben.

97 Stimmen

Außer wenn Android mir eine CharSequence in einem Callback übergibt und ich einen String brauche - dann rufe ich charSeq.toString() auf.

107 Stimmen

Aber denken Sie an diesen Vorbehalt aus dem CharSequence javadoc: Diese Schnittstelle verfeinert nicht die allgemeinen Verträge der equals y hashCode Methoden. Das Ergebnis des Vergleichs zweier Objekte, die die CharSequence ist daher im Allgemeinen, undefiniert . Jedes Objekt kann von einer anderen Klasse implementiert werden, und es gibt keine Garantie dafür, dass jede Klasse in der Lage ist, ihre Instanzen auf Gleichheit mit den Instanzen der anderen Klasse zu testen. Es ist daher unangebracht, beliebige CharSequence Instanzen als Elemente in einer Menge oder als Schlüssel in einer Karte.

0 Stimmen

@TrevorRobinson, Ist das nicht ein Designfehler?

92voto

Basil Bourque Punkte 256611

CharSequence = Schnittstelle
String = konkrete Umsetzung

Sie sagten:

Umwandlung von einem zum anderen

Es gibt keine Konvertierung von String .

Mit anderen Worten, jeder String es un CharSequence , aber nicht jeder CharSequence es un String .

Programmierung an einer Schnittstelle

Bei der Programmierung in Android werden die meisten Textwerte in CharSequence erwartet.

Warum ist das so? Was ist der Vorteil und was sind die wichtigsten Auswirkungen der Verwendung von CharSequence gegenüber String?

Im Allgemeinen ist die Programmierung für eine Schnittstelle besser als die Programmierung für konkrete Klassen. Dies führt zu Flexibilität, so dass wir zwischen konkreten Implementierungen einer bestimmten Schnittstelle wechseln können, ohne anderen Code zu zerstören.

Bei der Entwicklung eines API von verschiedenen Programmierern in verschiedenen Situationen verwendet werden soll, schreiben Sie Ihren Code so, dass er möglichst allgemeine Schnittstellen bietet und nutzt. Dies gibt dem aufrufenden Programmierer die Freiheit, verschiedene Implementierungen dieser Schnittstelle zu verwenden, je nachdem, welche Implementierung für seinen speziellen Kontext am besten geeignet ist.

Sehen Sie sich zum Beispiel die Java Collections Framework . Wenn Ihre API eine geordnete Sammlung von Objekten bereitstellt oder entgegennimmt, deklarieren Sie Ihre Methoden als mit List statt ArrayList , LinkedList oder eine andere Implementierung von Drittanbietern von List .

Wenn Sie eine kleine, schnelle Methode schreiben, die nur von Ihrem Code an einer bestimmten Stelle verwendet werden soll, im Gegensatz zum Schreiben einer API, die an mehreren Stellen verwendet werden soll, brauchen Sie sich nicht mit der Verwendung der allgemeineren Schnittstelle anstelle einer bestimmten konkreten Klasse zu befassen. Aber selbst dann schadet es nicht, die allgemeinste Schnittstelle zu verwenden, die es gibt.

Worin bestehen die Hauptunterschiede, und welche Probleme sind bei ihrer Verwendung zu erwarten?

  • Mit einem String Sie wissen, dass Sie einen einzigen Text haben, der sich vollständig im Speicher befindet und unveränderlich ist.
  • Mit einem CharSequence Sie wissen nicht, was die Besonderheiten der konkreten Implementierung sein könnten.

En CharSequence Objekt kann einen riesigen Textbrocken darstellen und hat daher Auswirkungen auf den Speicher. Oder es kann sich um viele Textstücke handeln, die separat verfolgt werden und die zusammengefügt werden müssen, wenn Sie toString und hat daher Leistungsprobleme. Die Implementierung kann sogar Text von einem entfernten Dienst abrufen und hat daher Auswirkungen auf die Latenzzeit.

und die Umwandlung von einem zum anderen?

Im Allgemeinen werden Sie nicht hin und her konvertieren. A String ist a CharSequence . Wenn Ihre Methode deklariert, dass sie eine CharSequence kann der aufrufende Programmierer eine String Objekt, oder kann etwas anderes übergeben, wie zum Beispiel ein StringBuffer o StringBuilder . Der Code Ihrer Methode verwendet einfach das, was übergeben wurde, und ruft eine der CharSequence Methoden.

Am ehesten kämen Sie einer Umwandlung nahe, wenn Ihr Code eine CharSequence und Sie wissen, dass Sie eine String . Vielleicht haben Sie eine Schnittstelle zu altem Code, der für String Klasse und nicht in die CharSequence Schnittstelle. Oder vielleicht arbeitet Ihr Code intensiv mit dem Text, z. B. durch wiederholte Schleifen oder andere Analysen. In diesem Fall wollen Sie alle möglichen Leistungseinbußen nur einmal in Kauf nehmen, also rufen Sie toString Vorne. Fahren Sie dann mit Ihrer Arbeit fort, indem Sie das, was Sie als einen einzigen Text kennen, vollständig aus dem Gedächtnis abrufen.

Verdrehte Geschichte

Beachten Sie die Kommentare zur akzeptierte Antwort . Die CharSequence Schnittstelle wurde nachträglich in bestehende Klassenstrukturen eingebaut, so dass es einige wichtige Feinheiten gibt ( equals() & hashCode() ). Beachten Sie die verschiedenen Java-Versionen (1, 2, 4 und 5), die auf den Klassen/Schnittstellen vermerkt sind - da hat sich im Laufe der Jahre so einiges getan. Idealerweise CharSequence wäre von Anfang an vorhanden gewesen, aber so ist das Leben.

Mein Klassendiagramm unten kann Ihnen helfen, das Gesamtbild der Stringtypen in Java 7/8 zu sehen. Ich bin mir nicht sicher, ob alle diese Typen in Android vorhanden sind, aber der Gesamtzusammenhang kann sich für Sie als nützlich erweisen.

diagram of various string-related classes and interfaces

4 Stimmen

Haben Sie dieses Diagramm selbst erstellt? Ich frage mich, ob es einen Katalog mit solchen Diagrammen für verschiedene Datenstrukturen gibt.

7 Stimmen

@user171943 Von mir verfasst, handgefertigt mit OmniGraffle App der OmniGroup.

40voto

Sham Punkte 409

Ich glaube, es ist am besten, CharSequence zu verwenden. Der Grund dafür ist, dass String implementiert CharSequence, daher können Sie einen String in eine CharSequence übergeben, JEDOCH können Sie nicht eine CharSequence in einen String übergeben, da CharSequence nicht String implementiert. ALSO, in Android die EditText.getText() Methode gibt ein Editable zurück, das auch CharSequence implementiert und leicht in ein solches übergeben werden kann, während es nicht leicht in einen String übergeben werden kann. CharSequence beherrscht alles!

10 Stimmen

Das können Sie tun charSequence.toString()

2 Stimmen

@jorge: Das ist allerdings relativ ineffizient, wenn die Sequenz veränderbar ist (oder aus irgendeinem Grund eine Kopie der Zeichen benötigt, um eine unveränderbare Zeichenfolge zu erstellen).

23voto

Itay Maman Punkte 29121

Die Verwendung einer Schnittstelle ermöglicht es im Allgemeinen, die Implementierung mit minimalem Kollateralschaden zu variieren. Obwohl java.lang.String sehr beliebt sind, kann es sein, dass man in bestimmten Kontexten eine andere Implementierung verwenden möchte. Indem die API um CharSequences und nicht um Strings herum aufgebaut wird, bietet der Code die Möglichkeit, dies zu tun.

9voto

Crypth Punkte 1525

Ein Problem, das im praktischen Android-Code auftritt, ist, dass der Vergleich mit CharSequence.equals zwar gültig ist, aber nicht unbedingt wie vorgesehen funktioniert.

EditText t = (EditText )getView(R.id.myEditText); // Contains "OK"
Boolean isFalse = t.getText().equals("OK"); // will always return false.

Der Vergleich sollte durchgeführt werden durch

("OK").contentEquals(t.GetText());

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X