web-dev-qa-db-ja.com

JavaのCharSequence VS String?

Androidでのプログラミングでは、ほとんどのテキスト値はCharSequenceで期待されています。

何故ですか? CharSequenceよりもStringを使用する主な影響は何ですか?

主な違いは何ですか?また、それらを使用し、ある問題から別の問題に変換するときに予想される問題は何ですか?

398
e-satis

文字列はCharSequences なので、文字列だけを使用でき、心配する必要はありません。 Androidは、StringBuffersのような他のCharSequenceオブジェクトも指定できるようにすることで、単に役立つことを試みているだけです。

330
Zarkonnen

このクラス図は、Java 7/8の文字列型の全体像を見るのに役立ちます。これらのすべてがAndroidに存在するかどうかはわかりませんが、全体的なコンテキストが依然として有用であることがわかります。

また、 受け入れられた回答 に対するコメントにも注意してください。 CharSequenceインターフェイスは既存のクラス構造に後付けされたため、いくつかの重要な微妙な点があります(equals()hashCode())。クラス/インターフェースでタグ付けされたJava(1、2、4、5)のさまざまなバージョンに注目してください。長年にわたってかなりの混乱が生じています。理想的にはCharSequenceは最初から適切に配置されていたはずですが、それは人生です。

diagram of various string-related classes and interfaces

44
Basil Bourque

CharSequenceを使用するのが最善だと思います。理由は、StringがCharSequenceを実装するためです。したがって、CharSequenceはStringを実装できないため、CharSequenceにStringを渡すことができますが、CharSequenceをStringに渡すことはできません。また、Androidでは、EditText.getText()メソッドはEditableを返します。これは、CharSequenceも実装しており、Stringに簡単に渡すことができますが、簡単に渡すことができます。 CharSequenceがすべてを処理します!

36
Sham

一般に、インターフェイスを使用すると、付随的な損傷を最小限に抑えて実装を変更できます。 Java.lang.Stringは非常に人気がありますが、特定のコンテキストでは別の実装を使用したい場合があります。文字列ではなくCharSequencesを中心にAPIを構築することにより、コードはそれを行う機会を与えます。

23
Itay Maman

これはほぼ確実にパフォーマンス上の理由です。たとえば、文字列を含む500k ByteBufferを通過するパーサーを想像してください。

文字列コンテンツを返すには、3つのアプローチがあります。

  1. 解析時にString []を一度に1文字ずつ作成します。これにはかなりの時間がかかります。 .equalsの代わりに==を使用して、キャッシュされた参照を比較できます。

  2. 解析時にオフセットを使用してint []を構築し、get()が発生したときに動的にStringを構築します。各文字列は新しいオブジェクトになるため、戻り値をキャッシュせず、==を使用します

  3. 解析時にCharSequence []を構築します。 (バイトバッファへのオフセット以外の)新しいデータは保存されないため、解析は#1よりはるかに低くなります。取得時には、文字列を作成する必要はありません。したがって、既存のオブジェクトへの参照のみを返すため、取得パフォーマンスは#1(#2よりはるかに優れています)に等しくなります。

CharSequenceを使用して得られる処理の利点に加えて、データを複製しないことでメモリフットプリントも削減します。たとえば、テキストの3つの段落を含むバッファがあり、3つすべてまたは1つの段落のいずれかを返す場合、これを表すには4つの文字列が必要です。 CharSequenceを使用すると、データを含む1つのバッファーと、開始と長さを追跡するCharSequence実装の4つのインスタンスのみが必要です。

8
Phil Lello

実際の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()); 
7
Crypth

CharSequence

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();
}

ひも

StringCharSequenceの一種であると言えます。ただし、CharSequenceとは異なり、これは実際のクラスなので、そこからオブジェクトを作成できます。だからあなたはこれを行うことができます:

String myString = new String();

しかし、あなたはこれを行うことはできません:

CharSequence myCharSequence = new CharSequence(); // error: 'CharSequence is abstract; cannot be instantiated

CharSequenceStringが準拠しているルールのリストにすぎないため、次のようにできます。

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();
}
3
Suragch

CharSequencename__はインターフェースであり、Stringname__はそれを実装します。 Stringname__をインスタンス化することはできますが、インターフェイスであるため、CharSequencename__に対してインスタンス化することはできません。他の実装は、公式のJava WebサイトのCharSequencename__にあります。

0
Xiaogang