私はこれを読みます 前の投稿 。 CharSequence
が String
を実装し、CharSequence
が文字のシーケンスであるという事実を除いて、String
とStringの正確な違いは何ですか?例えば:
CharSequence obj = "hello";
String str = "hello";
System.out.println("output is : " + obj + " " + str);
「hello」がobj
に割り当てられ、再びstr
に割り当てられるとどうなりますか?
CharSequence
のほかに String
インターフェースを実装するいくつかのクラスがあります。これらの中には
StringBuilder
変更可能な可変長文字シーケンスの場合CharBuffer
変更可能な固定長の低レベル文字シーケンス用CharSequence
を受け入れるメソッドは、これらすべてに対して同様にうまく機能します。 String
のみを受け入れるメソッドは、変換が必要です。したがって、内部を気にしないすべての場所でCharSequence
を引数型として使用することは賢明です。ただし、実際にString
を返す場合は、String
を戻り値の型として使用する必要があります。呼び出し側のメソッドが実際にString
を必要とする場合、戻り値の可能な変換を避けるためです。
また、マップキーは変更してはならないため、マップではString
ではなくCharSequence
をキータイプとして使用する必要があることに注意してください。つまり、String
の不変の性質が不可欠な場合があります。
貼り付けたコードについては、単にコンパイルし、javap -v
を使用してJVMバイトコードを確認します。ここで、obj
とstr
の両方が同じ定数オブジェクトへの参照であることがわかります。 String
は不変なので、この種の共有は大丈夫です。
String
の+
演算子は、さまざまなStringBuilder.append
呼び出しの呼び出しとしてコンパイルされます。だからそれは同等です
System.out.println(
(new StringBuilder())
.append("output is : ")
.append((Object)obj)
.append(" ")
.append(str)
.toString()
)
コンパイラーjavac 1.6.0_33
がStringBuilder.append(Object)
の代わりにStringBuilder.append(CharSequence)
を使用して+ obj
をコンパイルすることに少し驚いていることを告白しなければなりません。前者はおそらくオブジェクトのtoString()
メソッドへの呼び出しを伴うのに対して、後者はより効率的な方法で可能になるはずです。一方、String.toString()
は、単にString
自体を返すため、ペナルティはほとんどありません。したがって、StringBuilder.append(String)
は1つのメソッド呼び出しでより効率的になる可能性があります。
1つはインターフェイス( CharSequence
)で、もう1つはそのインターフェイスの具体的な実装( String
)です。
CharSequence animal = "cat" // `String` object presented as the interface `CharSequence`.
インターフェイスとしては、通常CharSequence
がString
よりも一般的に見られますが、いくつかのねじれた歴史により、インターフェイスが何年も定義されていましたafter実装。そのため、古いAPIではString
がよく見られますが、新しいAPIではCharSequence
が引数と戻り値の型の定義に使用される傾向があります。
最近では、一般的にAPI /フレームワークは主にインターフェースのエクスポートに、具体的なクラスの二次的なエクスポートに焦点を合わせる必要があることを知っています。しかし、私たちはこのレッスンをいつもそれほどよく知っていませんでした。
String
クラスはJavaで最初に登場しました。後になってから、彼らはCharSequence
という正面向きのインターフェースを配置しました。
少しの歴史が理解に役立つかもしれません。
初期の頃、Javaは、業界をアニメーション化するインターネット/ Webマニアのために、少し前に市場に駆けつけました。一部のライブラリは、本来考えられていたほど熟考されていませんでした。文字列処理はそれらの領域の1つでした。
また、Javaは、最も初期の生産指向の非アカデミック オブジェクト指向プログラミング(OOP) 環境の1つでした。 OOPの唯一の成功した実世界のラバーミーツザロード実装は、 Smalltalk のいくつかの限定バージョンであり、その後 Objective-C with NeXTSTEP / OpenStep したがって、多くの実践的な教訓はまだ学ばれていませんでした。
Javaは String
クラスと StringBuffer
クラスで始まりました。しかし、これら2つのクラスは無関係であり、継承やインターフェースによって互いに結び付けられていません。後で、Javaチームは、文字列関連の実装を相互交換可能にするために、文字列関連の実装を統一するタイがあるべきだと認識しました。 Java 4では、チームは CharSequence
インターフェースを追加し、そのインターフェースをStringおよびString Bufferに遡及的に実装し、別の実装を追加しました CharBuffer
。後でJava 5に StringBuilder
が追加されました。これは基本的に非同期であるため、StringBuffer
の多少速いバージョンです。
そのため、これらの文字列指向のクラスは少し複雑であり、学ぶのは少し混乱します。 String
オブジェクトを取得して返すために、多くのライブラリとインターフェイスが構築されました。現在、このようなライブラリは一般的にCharSequence
を期待するように構築されるべきです。ただし、(a)String
は依然としてマインドスペースを支配しているようです。(b)さまざまなCharSequence
実装を混在させると、微妙な技術的な問題が発生する可能性があります。後知恵の20/20ビジョンを見ると、このすべての文字列をより適切に処理できたはずであることがわかりますが、ここにあります。
理想的には、Javaは、 String
を使用するのと同じように、現在Collection
を使用している多くの場所で使用されるインターフェースおよび/またはスーパークラスで開始されます。 List
インターフェースの代わりに ArrayList
または LinkedList
実装。
CharSequence
の主な違いは、 実装 ではなく、 interface であることです。つまり、CharSequence
を直接インスタンス化することはできません。むしろ、そのインターフェースを実装するクラスの1つをインスタンス化します。
たとえば、ここにはx
のように見えるCharSequence
がありますが、その下は実際にはStringBuilder
オブジェクトです。
CharSequence x = new StringBuilder( "dog" );
これは、文字列リテラルを使用する場合、それほど明白ではありません。文字を引用符で囲んだソースコードを表示する場合、コンパイラはそれをStringオブジェクトに変換していることに注意してください。
CharSequence y = "cat"; // Looks like a CharSequence but is actually a String instance.
この他の質問 で説明したように、"cat"
とnew String("cat")
の間には微妙な違いがいくつかありますが、ここでは無関係です。
このクラス図は、ガイドに役立つ場合があります。 Javaのバージョンに注目しました。これらのバージョンでは、これらのクラスとインターフェースを介してどれだけの変化が生じているかを示しています。
ますます多くの emoji および Unicode サポートの連続したバージョンに付属している他の文字を除き、近年ではあまり変更されていませんJavaでテキストを操作するために…Java 13.まで.
Java 13は、新機能のプレビューを提供する場合があります:テキストブロック。これにより、SQLなどの埋め込みコード文字列の記述がより便利になります。 JEP 355 を参照してください。
この作業の前に JEP 326:Raw String Literals(Preview) がありました。
CharSequence
はコントラクト( interface )であり、String
はこのコントラクトの 実装 です。
public final class String extends Object
implements Serializable, Comparable<String>, CharSequence
documentation for CharSequence
は次のとおりです。
CharSequenceは、読み取り可能なchar値のシーケンスです。このインターフェイスは、さまざまな種類のcharシーケンスへの統一された読み取り専用アクセスを提供します。 char値は、基本多言語面(BMP)またはサロゲートの文字を表します。詳細については、Unicode文字表現を参照してください。
stringがCharSequenceを実装し、Stringが文字のシーケンスであるという事実以外。
コードではいくつかのことが起こります。
CharSequence obj = "hello";
これにより、String
オブジェクトであるString
リテラル"hello"
が作成されます。 String
を実装するCharSequence
であると同時に、CharSequence
でもあります。 ( インターフェイスへのコーディングに関するこの投稿 を読むことができます)。
次の行:
String str = "hello";
もう少し複雑です。 JavaのString
リテラルはプールに保持される(インターン)ため、この行の"hello"
は最初の行の"hello"
と同じオブジェクト(ID)です。 。したがって、この行は、String
に同じstr
リテラルのみを割り当てます。
この時点で、obj
とstr
は両方ともString
リテラル"hello"
への参照であるため、equals
、==
であり、両方ともString
およびCharSequence
。
このコードをテストして、今書いた内容を実際に見せることをお勧めします。
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));
}
私はそれが一種の明白であることを知っていますが、CharSequenceはインターフェイスですが、Stringは具体的なクラスです:)
Java.lang.Stringは、このインターフェイスの実装です...
UTF-8を検討してください。 UTF-8では、Unicodeコードポイントは1バイト以上から構築されます。 UTF-8バイト配列をカプセル化するクラスは、CharSequenceインターフェイスを実装できますが、ほとんどの場合、文字列ではありません。確かに、Stringが期待されるUTF-8バイト配列を渡すことはできませんが、CharSequenceを許可するためにコントラクトが緩和されると、CharSequenceを実装するUTF-8ラッパークラスを確実に渡すことができます。私のプロジェクトでは、XMLのデータ圧縮を提供するCBTF8Field(圧縮バイナリ転送形式-8ビット)というクラスを開発しており、CharSequenceインターフェイスを使用してCBTF8バイト配列から文字配列(UTF-16)への変換を実装しようとしています)およびバイト配列(UTF-8)。
ここに来たのは、サブシーケンス契約を完全に理解するためです。
CharSequence のJava APIから:
CharSequenceは、読み取り可能な文字のシーケンスです。このインターフェイスは、さまざまな種類の文字シーケンスへの統一された読み取り専用アクセスを提供します。
このインターフェイスは、すべてのメソッド名の一貫性を保つために String 、 CharBuffer 、および StringBuffer によって使用されます。
CharSequenceには、Stringで使用できる非常に便利なメソッドはありません。ドキュメントを参照したくない場合は、objと入力します。およびstr。
そして、あなたのコンピレーターがあなたに提供する方法を見てください。それが私にとっての基本的な違いです。