Bei der Programmierung in Android werden die meisten Textwerte in erwartet CharSequence
.
Warum ist das so? Was ist der Vorteil und was sind die Hauptauswirkungen der Verwendung von CharSequence
Over String
?
Was sind die Hauptunterschiede und welche Probleme werden erwartet, wenn Sie sie verwenden und von einem zum anderen konvertieren?
java
string
charsequence
e-satis
quelle
quelle
Antworten:
Strings sind CharSequences , Sie können also einfach Strings verwenden und müssen sich keine Sorgen machen. Android versucht lediglich, hilfreich zu sein, indem Sie auch andere CharSequence-Objekte wie StringBuffers angeben können.
quelle
CharSequence
Javadoc: Diese Schnittstelle verfeinert nicht die allgemeinen Verträge der Methodenequals
undhashCode
. Das Ergebnis des Vergleichs zweier implementierter ObjekteCharSequence
ist daher im Allgemeinen undefiniert . Jedes Objekt kann von einer anderen Klasse implementiert werden, und es gibt keine Garantie dafür, dass jede Klasse ihre Instanzen auf Gleichheit mit denen der anderen testen kann. Es ist daher unangemessen, beliebigeCharSequence
Instanzen als Elemente in einer Menge oder als Schlüssel in einer Karte zu verwenden.CharSequence
war eine Nachrüstung in JDK 1.4, um eine gemeinsame Schnittstelle mit eingeschränktem Verwendungszweck für Objekte einzuführen, die Zeichenfolgen enthalten. Einige dieser Objekte enthalten einen anderen Status, daher ist es möglicherweise nicht sinnvoll,Object.equals
"enthält dieselbe Zeichenfolge" zu definieren . NIOCharBuffer
legt beispielsweise nur die Zeichen zwischenposition
undlimit
als offen ,CharSequence
obwohl möglicherweise viele andere Zeichen enthalten sind.equals
/hashCode
anObject
erster Stelle ....Object
oderCharSequence
, keine Schnittstelle erforderlich ist Gleichheit sanity zwischen Implementierungen zu bieten. EsCollection
sind keine zwei erforderlich, um die Gleichheit zwischen derCollection
Schnittstelle zu gewährleisten , aber sie können, wenn sie dies wünschen. IMHOCharSequence
sollte auf Eingaben beschränkt und weniger für Rückgabetypen verwendet werden.CharSequence
= SchnittstelleString
= konkrete UmsetzungCharSequence
ist eine Schnittstelle .String
ist eine solche Klasse, eine konkrete Umsetzung vonCharSequence
.Du sagtest:
Es erfolgt keine Konvertierung von
String
.String
Objekt ist einCharSequence
.CharSequence
kann eine produzierenString
. Rufen Sie anCharSequence::toString
. Wenn dasCharSequence
zufällig a istString
, gibt die Methode einen Verweis auf ihr eigenes Objekt zurück.Mit anderen Worten, jeder
String
ist einCharSequence
, aber nicht jederCharSequence
ist einString
.Programmierung auf eine Schnittstelle
Im Allgemeinen ist das Programmieren auf eine Schnittstelle besser als das Programmieren auf konkrete Klassen. Dies bietet Flexibilität, sodass wir zwischen konkreten Implementierungen einer bestimmten Schnittstelle wechseln können, ohne anderen Code zu beschädigen.
Wenn Sie eine API entwickeln , die von verschiedenen Programmierern in verschiedenen Situationen verwendet werden soll, schreiben Sie Ihren Code, um die allgemeinsten Schnittstellen zu erhalten und zu übernehmen. Dies gibt dem aufrufenden Programmierer die Freiheit, verschiedene Implementierungen dieser Schnittstelle zu verwenden, je nachdem, welche Implementierung für ihren jeweiligen Kontext am besten geeignet ist.
Schauen Sie sich beispielsweise das Java Collections Framework an . Wenn Ihr API gibt oder nimmt eine geordnete Sammlung von Objekten, erklären Ihre Methoden wie die Verwendung
List
nichtArrayList
,LinkedList
oder jede andere 3rd-Party - ImplementierungList
.Wenn Sie eine schnelle und schmutzige kleine Methode schreiben, die nur von Ihrem Code an einer bestimmten Stelle verwendet werden soll, anstatt eine API zu schreiben, die an mehreren Stellen verwendet werden soll, müssen Sie sich nicht mit der Verwendung der allgemeineren Benutzeroberfläche befassen, sondern mit einer bestimmten konkreten Klasse. Aber selbst dann tut es weh, die allgemeinste Oberfläche zu verwenden, die Sie können.
String
wissen Sie, dass Sie einen einzigen Text haben, der vollständig im Gedächtnis bleibt und unveränderlich ist.CharSequence
wissen Sie nicht, welche Besonderheiten die konkrete Implementierung haben könnte.Das
CharSequence
Objekt kann einen enormen Textblock darstellen und hat daher Auswirkungen auf das Gedächtnis. Oder es können viele Textblöcke separat verfolgt werden, die beim Aufrufen zusammengefügt werdentoString
müssen und daher Leistungsprobleme aufweisen. Die Implementierung ruft möglicherweise sogar Text von einem Remotedienst ab und hat daher Auswirkungen auf die Latenz.Sie werden im Allgemeinen nicht hin und her konvertieren. A
String
ist aCharSequence
. Wenn Ihre Methode deklariert, dass es a benötigtCharSequence
, kann der aufrufende Programmierer einString
Objekt oder etwas anderes wie einStringBuffer
oder übergebenStringBuilder
. Der Code Ihrer Methode verwendet einfach alles, was übergeben wird, und ruft eine derCharSequence
Methoden auf.Die Konvertierung kommt Ihnen am nächsten, wenn Ihr Code eine erhält
CharSequence
und Sie wissen, dass Sie eine benötigenString
. Möglicherweise sind Sie mit altem Code verbunden, der in dieString
Klasse geschrieben wurde, anstatt in dieCharSequence
Schnittstelle geschrieben zu werden. Oder Ihr Code arbeitet intensiv mit dem Text, z. B. wiederholte Schleifen oder andere Analysen. In diesem Fall möchten Sie einen möglichen Leistungstreffer nur einmal ausführen, also rufen Sie im VoraustoString
an. Fahren Sie dann mit Ihrer Arbeit fort, indem Sie einen einzigen Text verwenden, von dem Sie wissen, dass er vollständig im Gedächtnis bleibt.Verdrehte Geschichte
Beachten Sie die Kommentare zur akzeptierten Antwort . Die
CharSequence
Schnittstelle wurde an vorhandenen Klassenstrukturen nachgerüstet, sodass einige wichtige Feinheiten (equals()
&hashCode()
) vorhanden sind. Beachten Sie die verschiedenen Versionen von Java (1, 2, 4 & 5), die auf den Klassen / Schnittstellen markiert sind - im Laufe der Jahre einiges an Abwanderung. IdealerweiseCharSequence
wäre es von Anfang an vorhanden gewesen, aber so ist das Leben.Mein Klassendiagramm unten kann Ihnen helfen, das Gesamtbild der Zeichenfolgentypen in Java 7/8 zu sehen. Ich bin mir nicht sicher, ob all dies in Android vorhanden ist, aber der Gesamtkontext kann sich für Sie dennoch als nützlich erweisen.
quelle
Ich glaube, es ist am besten, CharSequence zu verwenden. Der Grund dafür ist, dass String CharSequence implementiert. Daher können Sie einen String an eine CharSequence übergeben. Sie können jedoch keine CharSequence an einen String übergeben, da CharSequence keinen String implementiert. AUCH in Android gibt die
EditText.getText()
Methode eine Bearbeitbare zurück, die auch CharSequence implementiert und einfach in eine, aber nicht einfach in eine Zeichenfolge übergeben werden kann. CharSequence kümmert sich um alles!quelle
charSequence.toString()
Im Allgemeinen können Sie mithilfe einer Schnittstelle die Implementierung mit minimalem Kollateralschaden variieren. Obwohl java.lang.String sehr beliebt ist, kann es sein, dass in bestimmten Kontexten eine andere Implementierung verwendet werden soll. Durch das Erstellen der API um CharSequences anstelle von Strings bietet der Code die Möglichkeit, dies zu tun.
quelle
Dies ist mit ziemlicher Sicherheit ein Leistungsgrund. Stellen Sie sich beispielsweise einen Parser vor, der einen 500-KByte-ByteBuffer mit Zeichenfolgen durchläuft.
Es gibt drei Ansätze zum Zurückgeben des Zeichenfolgeninhalts:
Erstellen Sie einen String [] zur Analysezeit, jeweils ein Zeichen. Dies wird spürbar lange dauern. Wir können == anstelle von .equals verwenden, um zwischengespeicherte Referenzen zu vergleichen.
Erstellen Sie ein int [] mit Offsets zur Analysezeit und erstellen Sie dann dynamisch einen String, wenn ein get () auftritt. Jeder String ist ein neues Objekt, daher werden keine zurückgegebenen Werte zwischengespeichert und == verwendet
Erstellen Sie zur Analysezeit eine CharSequence []. Da keine neuen Daten gespeichert werden (außer Offsets im Bytepuffer), ist das Parsen viel niedriger als # 1. Zum Zeitpunkt des Abrufs müssen wir keinen String erstellen, daher ist die Abrufleistung gleich # 1 (viel besser als # 2), da wir nur einen Verweis auf ein vorhandenes Objekt zurückgeben.
Zusätzlich zu den Verarbeitungsgewinnen, die Sie mit CharSequence erzielen, reduzieren Sie auch den Speicherbedarf, indem Sie keine Daten duplizieren. Wenn Sie beispielsweise einen Puffer mit 3 Textabschnitten haben und entweder alle 3 oder einen einzelnen Absatz zurückgeben möchten, benötigen Sie 4 Zeichenfolgen, um dies darzustellen. Mit CharSequence benötigen Sie nur 1 Puffer mit den Daten und 4 Instanzen einer CharSequence-Implementierung, die den Start und die Länge verfolgt.
quelle
CharSequence
Implementierung rollen .CharSequence
ist eine Schnittstelle - per Definition enthält es keine der von Ihnen diskutierten Implementierungsdetails, da es keine eigene Implementierung hat . AString
ist eine von mehreren konkreten Klassen, die dieCharSequence
Schnittstelle implementieren . AlsoString
ist a einCharSequence
. Sie können die Leistungsdetails vonString
vsStringBuffer
vs vergleichenStringBuilder
, aber nichtCharSequence
. Das Schreiben von „Verarbeitungsgewinnen, die Sie mit CharSequence erzielen“ ist bedeutungslos.Ein Problem, das im praktischen Android-Code auftritt, ist, dass der Vergleich mit CharSequence.equals gültig ist, aber nicht unbedingt wie beabsichtigt funktioniert.
Der Vergleich sollte von durchgeführt werden
quelle
Zeichenfolge
A
CharSequence
ist eine Schnittstelle, keine tatsächliche Klasse. Eine Schnittstelle ist nur eine Reihe von Regeln (Methoden), die eine Klasse enthalten muss, wenn sie die Schnittstelle implementiert. In AndroidCharSequence
ist a ein Regenschirm für verschiedene Arten von Textzeichenfolgen. Hier sind einige der häufigsten:String
(unveränderlicher Text ohne Styling-Bereiche)StringBuilder
(veränderbarer Text ohne Styling-Bereiche)SpannableString
(unveränderlicher Text mit Stilspannen)SpannableStringBuilder
(veränderbarer Text mit Stilspannen)(Mehr über die Unterschiede zwischen diesen können Sie hier lesen .)
Wenn Sie ein
CharSequence
Objekt haben, ist es tatsächlich ein Objekt einer der implementierten KlassenCharSequence
. Zum Beispiel:Der Vorteil eines allgemeinen Schirmtyps
CharSequence
besteht darin, dass Sie mehrere Typen mit einer einzigen Methode verarbeiten können. Wenn ich zum Beispiel eine Methode habe, die aCharSequence
als Parameter verwendet, könnte ich aString
oder a übergebenSpannableStringBuilder
und sie würde beide behandeln.String
Man könnte sagen, dass a
String
nur eine Art von istCharSequence
. Im Gegensatz dazuCharSequence
handelt es sich jedoch um eine tatsächliche Klasse, sodass Sie daraus Objekte erstellen können. Sie könnten also Folgendes tun:aber das kannst du nicht machen:
Da
CharSequence
es sich nur um eine Liste von Regeln handelt, die denString
Anforderungen entsprechen, können Sie Folgendes tun:Das bedeutet, dass
CharSequence
es immer dann in Ordnung ist , wenn eine Methode nach a fragtString
.Das Gegenteil ist jedoch nicht der Fall. Wenn die Methode einen
String
Parameter verwendet, können Sie ihm nichts übergeben, von dem nur allgemein bekannt istCharSequence
, dass es sich um einen Parameter handelt , da es sich möglicherweise tatsächlich um einenSpannableString
oder einen anderen Parameter handeltCharSequence
.quelle
CharSequence
ist eine Schnittstelle undString
implementiert sie. Sie können a instanziieren,String
aber das können Sie nicht,CharSequence
da es sich um eine Schnittstelle handelt. Weitere Implementierungen finden SieCharSequence
auf der offiziellen Java-Website.quelle
CharSequence ist eine lesbare Folge von Zeichenwerten, die String implementiert. Es hat 4 Methoden
Weitere Informationen finden Sie in der Dokumentation zur CharSequence-Dokumentation
quelle
CharSequence
nicht implementiertString
. Das Gegenteil ist jedoch der Fall.