Androidでのプログラミングでは、ほとんどのテキスト値はCharSequence
で期待されています。
何故ですか? CharSequence
よりもString
を使用する主な影響は何ですか?
主な違いは何ですか?また、それらを使用し、ある問題から別の問題に変換するときに予想される問題は何ですか?
文字列はCharSequences なので、文字列だけを使用でき、心配する必要はありません。 Androidは、StringBuffersのような他のCharSequenceオブジェクトも指定できるようにすることで、単に役立つことを試みているだけです。
このクラス図は、Java 7/8の文字列型の全体像を見るのに役立ちます。これらのすべてがAndroidに存在するかどうかはわかりませんが、全体的なコンテキストが依然として有用であることがわかります。
また、 受け入れられた回答 に対するコメントにも注意してください。 CharSequence
インターフェイスは既存のクラス構造に後付けされたため、いくつかの重要な微妙な点があります(equals()
&hashCode()
)。クラス/インターフェースでタグ付けされたJava(1、2、4、5)のさまざまなバージョンに注目してください。長年にわたってかなりの混乱が生じています。理想的にはCharSequence
は最初から適切に配置されていたはずですが、それは人生です。
CharSequenceを使用するのが最善だと思います。理由は、StringがCharSequenceを実装するためです。したがって、CharSequenceはStringを実装できないため、CharSequenceにStringを渡すことができますが、CharSequenceをStringに渡すことはできません。また、Androidでは、EditText.getText()
メソッドはEditableを返します。これは、CharSequenceも実装しており、Stringに簡単に渡すことができますが、簡単に渡すことができます。 CharSequenceがすべてを処理します!
一般に、インターフェイスを使用すると、付随的な損傷を最小限に抑えて実装を変更できます。 Java.lang.Stringは非常に人気がありますが、特定のコンテキストでは別の実装を使用したい場合があります。文字列ではなくCharSequencesを中心にAPIを構築することにより、コードはそれを行う機会を与えます。
これはほぼ確実にパフォーマンス上の理由です。たとえば、文字列を含む500k ByteBufferを通過するパーサーを想像してください。
文字列コンテンツを返すには、3つのアプローチがあります。
解析時にString []を一度に1文字ずつ作成します。これにはかなりの時間がかかります。 .equalsの代わりに==を使用して、キャッシュされた参照を比較できます。
解析時にオフセットを使用してint []を構築し、get()が発生したときに動的にStringを構築します。各文字列は新しいオブジェクトになるため、戻り値をキャッシュせず、==を使用します
解析時にCharSequence []を構築します。 (バイトバッファへのオフセット以外の)新しいデータは保存されないため、解析は#1よりはるかに低くなります。取得時には、文字列を作成する必要はありません。したがって、既存のオブジェクトへの参照のみを返すため、取得パフォーマンスは#1(#2よりはるかに優れています)に等しくなります。
CharSequenceを使用して得られる処理の利点に加えて、データを複製しないことでメモリフットプリントも削減します。たとえば、テキストの3つの段落を含むバッファがあり、3つすべてまたは1つの段落のいずれかを返す場合、これを表すには4つの文字列が必要です。 CharSequenceを使用すると、データを含む1つのバッファーと、開始と長さを追跡するCharSequence実装の4つのインスタンスのみが必要です。
実際のAndroidコードで発生する問題は、それらをCharSequence.equalsと比較することは有効ですが、必ずしも意図したとおりに機能しないことです。
EditText t = (EditText )getView(R.id.myEditText); // Contains "OK"
Boolean isFalse = t.getText().equals("OK"); // will always return false.
比較は
("OK").contentEquals(t.GetText());
CharSequence
はインターフェースであり、実際のクラスではありません。インターフェイスは、インターフェイスを実装する場合にクラスに含める必要のあるルール(メソッド)のセットです。 Androidでは、CharSequence
はさまざまな種類のテキスト文字列の傘です。一般的なもののいくつかを次に示します。
String
(スタイリングスパンのない不変テキスト)StringBuilder
(スタイリングスパンのない可変テキスト)SpannableString
(スタイリングスパンを持つ不変テキスト)SpannableStringBuilder
(スタイリングスパンを含む可変テキスト)(これらの違いについて詳しく読むことができます こちら 。)
CharSequence
オブジェクトがある場合、それは実際にはCharSequence
を実装するクラスのいずれかのオブジェクトです。例えば:
CharSequence myString = "hello";
CharSequence mySpannableStringBuilder = new SpannableStringBuilder();
CharSequence
のような一般的なアンブレラ型を持つことの利点は、1つのメソッドで複数の型を処理できることです。たとえば、CharSequence
をパラメーターとして取るメソッドがある場合、String
またはSpannableStringBuilder
を渡すことができ、どちらかを処理します。
public int getLength(CharSequence text) {
return text.length();
}
String
はCharSequence
の一種であると言えます。ただし、CharSequence
とは異なり、これは実際のクラスなので、そこからオブジェクトを作成できます。だからあなたはこれを行うことができます:
String myString = new String();
しかし、あなたはこれを行うことはできません:
CharSequence myCharSequence = new CharSequence(); // error: 'CharSequence is abstract; cannot be instantiated
CharSequence
はString
が準拠しているルールのリストにすぎないため、次のようにできます。
CharSequence myString = new String();
つまり、メソッドがCharSequence
を要求するときはいつでも、String
を指定しても問題ありません。
String myString = "hello";
getLength(myString); // OK
// ...
public int getLength(CharSequence text) {
return text.length();
}
ただし、その逆は当てはまりません。メソッドがString
パラメータをとる場合、実際にはCharSequence
または他の種類のSpannableString
である可能性があるため、一般にCharSequence
としてのみ知られているものを渡すことはできません。
CharSequence myString = "hello";
getLength(myString); // error
// ...
public int getLength(String text) {
return text.length();
}
CharSequence
name__はインターフェースであり、String
name__はそれを実装します。 String
name__をインスタンス化することはできますが、インターフェイスであるため、CharSequence
name__に対してインスタンス化することはできません。他の実装は、公式のJava WebサイトのCharSequence
name__にあります。