106

この前の投稿を読みました。が実装され、文字のシーケンスであるCharSequenceという事実以外に、 String との正確な違いは何ですか? 例えば:StringCharSequenceString

CharSequence obj = "hello";
String str = "hello";
System.out.println("output is : " + obj + "  " + str);

"hello" が に割り当てられobj、再び に割り当てられるとどうなりstrますか?

4

8 に答える 8

104

一般的な違い

CharSequence以外にも、インターフェースを実装するクラスがいくつかありますString。これらの中には、

  • StringBuilder変更可能な可変長文字シーケンスの場合
  • CharBuffer変更可能な固定長の低レベル文字シーケンス用

を受け入れる任意のメソッドはCharSequence、これらすべてに対して同等に機能します。のみを受け入れるメソッドはString、変換が必要になります。したがってCharSequence、内部を気にしないすべての場所で引数型として使用するのが賢明です。ただしString、実際に を返す場合は、String戻り値の型として使用する必要があります。これは、呼び出し元のメソッドが実際にString.

Stringまた、マップ キーは変更してはならないため、マップは ではなくキー タイプとして使用する必要があることに注意してくださいCharSequence。つまり、 の不変の性質Stringが不可欠な場合があります。

特定のコード スニペット

貼り付けたコードについては、単にそれをコンパイルし、javap -v. objとの両方strが同じ定数オブジェクトへの参照であることがわかります。aStringは不変なので、この種の共有は問題ありません。

+演算子はString、さまざまな呼び出しの呼び出しとしてコンパイルされますStringBuilder.append。したがって、それは

System.out.println(
  (new StringBuilder())
  .append("output is : ")
  .append((Object)obj)
  .append(" ")
  .append(str)
  .toString()
)

私のコンパイラが の代わりにusing をjavac 1.6.0_33コンパイルすることに少し驚いたことを告白しなければなりません。前者はおそらくオブジェクトのメソッドの呼び出しを伴いますが、後者はより効率的な方法で可能になるはずです。一方、単純に自分自身を返すため、ペナルティはほとんどありません。その ため、約 1 つのメソッド呼び出しでより効率的になる可能性があります。+ objStringBuilder.append(Object)StringBuilder.append(CharSequence)toString()String.toString()StringStringBuilder.append(String)

于 2012-07-04T07:07:30.607 に答える
92

tl;dr

1 つはインターフェイス ( CharSequence) で、もう 1 つはそのインターフェイスの具体的な実装 ( String) です。

CharSequence animal = "cat"  // `String` object presented as the interface `CharSequence`.

ArrayListが であるのとList同じように、 もです。HashMapMapStringCharSequence

インターフェースとしては、通常は よりも のCharSequence方がよく見られますStringが、ねじれた歴史により、実装から数年後にインターフェースが定義されることになりました。そのため、古い API ではよく見かけますが、新しい API では引数と戻り値の定義に使用されるString傾向があります。CharSequence

詳細

最近では、一般的に、API/フレームワークは主にインターフェイスのエクスポートに焦点を当て、2 番目に具象クラスに焦点を当てる必要があることがわかっています。しかし、私たちはいつもこの教訓をよく知っていたわけではありません。

StringクラスはJavaで最初に登場しました。後になって初めて、彼らは正面向きのインターフェースを配置しましたCharSequence.

ねじれた歴史

少しの歴史が理解に役立つかもしれません。

初期の頃、Java は、インターネット/Web マニアが業界を活気づけていたため、時代よりも少し早く市場に投入されました。一部のライブラリは、本来あるべきほどよく考え抜かれていませんでした。文字列の処理は、その分野の 1 つです。

また、Java は、最も初期のプロダクション指向の非アカデミックなオブジェクト指向プログラミング (OOP)環境の 1 つでした。それ以前に成功した実世界のラバー ミート ザ ロード実装は、 SmallTalkのいくつかの限定バージョンであり、その後はNeXTSTEP / OpenStepを使用したObjective-Cでした。そのため、多くの実践的な教訓がまだ習得されていませんでした。

JavaはStringクラスとStringBufferクラスから始まりました。しかし、これら 2 つのクラスは無関係であり、継承やインターフェイスによって互いに関連付けられていません。その後、Java チームは、文字列関連の実装を交換可能にするために、それらの間に統一的な関係が必要であることに気付きました。Java 4 では、チームはインターフェイスを追加し、CharSequenceそのインターフェイスを String および String Buffer にさかのぼって実装し、別の実装を追加しましたCharBufferStringBuilder後にJava 5 で追加されたStringBuffer.

そのため、これらの文字列指向のクラスは少しごちゃごちゃしていて、学ぶのが少し混乱します。多くのライブラリとインターフェイスは、Stringオブジェクトを受け取って返すために構築されました。現在、そのようなライブラリは一般に期待するように構築する必要がありCharSequenceます。しかし、(a)String依然としてマインドスペースを支配しているようであり、(b) さまざまなCharSequence実装を混在させると、微妙な技術的問題が発生する可能性があります。後知恵の 20/20 ビジョンでは、このすべての文字列をより適切に処理できた可能性があることがわかりますが、ここにあります。

理想的には、Java は、またはの実装の代わりにまたはインターフェースStringを使用するのと同じように、現在 を使用している多くの場所で使用されるインターフェースおよび/またはスーパークラスから始めていたはずです。CollectionListArrayListLinkedList

インターフェイスとクラス

主な違いは、実装ではなくインターフェイスCharSequenceであるということです。つまり、 を直接インスタンス化することはできません。むしろ、そのインターフェースを実装するクラスの 1 つをインスタンス化します。CharSequence

たとえば、これxは のように見えますがCharSequence、その下には実際にはStringBuilderオブジェクトがあります。

CharSequence x = new StringBuilder( "dog" );  // Looks like a `CharSequence` but is actually a `StringBuilder` instance.

これは、文字列リテラルを使用すると、あまり明白ではなくなります。文字を引用符だけで囲んでいるソース コードを見ると、コンパイラはそれを String オブジェクトに変換していることに注意してください。

CharSequence y = "cat";  // Looks like a `CharSequence` but is actually a `String` instance.

リテラルとコンストラクター

この他の質問で説明されているように、"cat"との間にはいくつかの微妙な違いがありますが、ここでは関係ありません。new String("cat")

クラス図

このクラス図が参考になるかもしれません。これらのクラスとインターフェースを通じてどれだけの変更が行われたかを示しているように見える Java のバージョンに注目しました。

Java 8 のさまざまな文字列関連のクラスとインターフェイスを示す図

テキストブロック

多数のemojiを含むUnicode文字をさらに追加することを除けば、近年 Java でテキストを操作するための変更はあまりありません。テキストブロックまで。

テキスト ブロックは、複数行または文字エスケープを使用した文字列リテラルの退屈な処理を改善する新しい方法です。これにより、HTML、XML、SQL、または JSON などの埋め込みコード文字列の記述がはるかに便利になります。

JEP 378を引用するには:

テキスト ブロックは複数行の文字列リテラルであり、ほとんどのエスケープ シーケンスを必要とせず、予測可能な方法で文字列を自動的にフォーマットし、必要に応じて開発者がフォーマットを制御できるようにします。

テキスト ブロック機能は、新しいデータ型を導入しませ。テキスト ブロックは、リテラルを記述するための新しい構文にすぎません。従来のリテラル構文と同様に、テキスト ブロックはオブジェクトを生成します。テキスト ブロックは、上で説明したように、オブジェクトでもあるオブジェクトを生成します。StringStringStringCharSequence

SQL の例

JSR 378 をもう一度引用すると…</p>

「一次元」文字列リテラルの使用。

String query = "SELECT \"EMP_ID\", \"LAST_NAME\" FROM \"EMPLOYEE_TB\"\n" +
               "WHERE \"CITY\" = 'INDIANAPOLIS'\n" +
               "ORDER BY \"EMP_ID\", \"LAST_NAME\";\n";

「二次元」のテキスト ブロックの使用

String query = """
               SELECT "EMP_ID", "LAST_NAME" FROM "EMPLOYEE_TB"
               WHERE "CITY" = 'INDIANAPOLIS'
               ORDER BY "EMP_ID", "LAST_NAME";
               """;

JEP 378: Text Blocksに従って、テキスト ブロックはJava 15以降で検出されます。

JEP 355: Text Blocks (Preview)の下で、Java 13 で最初にプレビューされました。次に、Java 14 でJEP 368: Text Blocks (Second Preview)の下で再度プレビューしました。

この取り組みは、 JEP 326: Raw String Literals (Preview)によって先行されました。代わりに、テキスト ブロック機能を生成するために概念が作り直されました。

于 2014-10-22T01:18:47.693 に答える
22

CharSequenceはコントラクト ( interface ) であり、このコントラクトString実装です。

public final class String extends Object 
    implements Serializable, Comparable<String>, CharSequence

ドキュメントCharSequence次のとおりです。

CharSequence は、char 値の読み取り可能なシーケンスです。このインターフェイスは、多くの異なる種類の char シーケンスへの統一された読み取り専用アクセスを提供します。char 値は、Basic Multilingual Plane (BMP) またはサロゲートの文字を表します。詳細については、Unicode 文字表現を参照してください。

于 2012-07-04T07:10:02.957 に答える
12

String が CharSequence を実装し、String が文字のシーケンスであるという事実以外は。

コードでいくつかのことが起こります。

CharSequence obj = "hello";

これにより、オブジェクトであるStringリテラルが作成されます。を実装するであるため、それもです。(たとえば、インターフェイスへのコーディングに関するこの投稿を読むことができます)。"hello"StringStringCharSequenceCharSequence

次の行:

String str = "hello";

はもう少し複雑です。StringJava のリテラルはプール (interned) に保持されるため、この行の は最初の行"hello"の と同じオブジェクト (ID)です。"hello"したがって、この行は同じStringリテラルを に割り当てるだけstrです。

この時点で、objとはどちらもリテラルstrへの参照であるためであり、両方とも aと aです。String"hello"equals==StringCharSequence

このコードをテストして、私が書いたものを実際に表示することをお勧めします。

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));
}
于 2012-07-04T07:42:50.913 に答える
3

私はそれが一種の明白であることを知っていますが、CharSequence はインターフェースですが、String は具体的なクラスです:)

java.lang.String は、このインターフェースの実装です...

于 2012-07-04T07:03:01.843 に答える
2

CharSequenceの Java API から:

CharSequence は、読み取り可能な一連の文字です。このインターフェイスは、多くの異なる種類の文字シーケンスへの統一された読み取り専用アクセスを提供します。

このインターフェイスは、すべてのメソッド名の一貫性を保つために、 StringCharBuffer、およびStringBufferによって使用されます。

于 2012-07-04T07:06:45.173 に答える
2

Consider UTF-8. In UTF-8 Unicode code points are built from one or more bytes. A class encapsulating a UTF-8 byte array can implement the CharSequence interface but is most decidedly not a String. Certainly you can't pass a UTF-8 byte array where a String is expected but you certainly can pass a UTF-8 wrapper class that implements CharSequence when the contract is relaxed to allow a CharSequence. On my project, I am developing a class called CBTF8Field (Compressed Binary Transfer Format - Eight Bit) to provide data compression for xml and am looking to use the CharSequence interface to implement conversions from CBTF8 byte arrays to/from character arrays (UTF-16) and byte arrays (UTF-8).

The reason I came here was to get a complete understanding of the subsequence contract.

于 2013-09-20T19:10:16.407 に答える
1

charSequence には、String で使用できる非常に便利なメソッドがありません。ドキュメントを見たくない場合は、obj と入力します。とstr。

コンパイラが提供するメソッドを確認してください。それが私にとっての基本的な違いです。

于 2012-07-04T07:10:07.667 に答える