Javaチャレンジャー#2:文字列の比較

Javaチャレンジャー#2:文字列の比較


いつものように、コースの開始にはかなり遅れているので、昨日、新しいスレッド「Java Developer」の間で2回目のレッスンを開催しました。 しかし、これは人生のささいなことですが、今のところ、Java Challengersの一連の記事を公開し続けています。


Javaでは、 Stringクラスはchar配列をカプセル化します( 翻訳者のメモ-Java 9では既にbyte配列になっています。Java9の文字列のコンパクト化を参照 )。 簡単に言えば、 Stringは、単語、文、またはその他の構成要素を構成するために使用される文字の配列です。


カプセル化は、オブジェクト指向プログラミングの最も強力な概念の1つです。 カプセル化のおかげで、 Stringクラスの仕組みを知る必要はありません。 インターフェースのメソッドを知る必要があるだけです。



JavaのStringクラスを見ると、 char配列がどのようにカプセル化されているかがわかります。


 public String(char value[]) { this(value, 0, value.length, null); } 

カプセル化をよりよく理解するために、物理オブジェクトであるマシンを想像してください。 車を運転するには、ボンネットの下で車がどのように機能するかを知る必要がありますか? もちろんそうではありませんが、車のインターフェースが何をしているのかを知っておく必要があります:アクセルペダル、ブレーキ、ハンドル。 これらの各インターフェイスは、特定のアクションをサポートしています:加速、ブレーキ、左折、右折。 オブジェクト指向プログラミングでも同じことが言えます。


Java Challengersシリーズの最初の記事はメソッドのオーバーロードに関するもので、 Stringクラスで広く使用されています。 オーバーロードにより、クラスが非常に柔軟になります。


 public String(String original) {} public String(char value[], int offset, int count) {} public String(int[] codePoints, int offset, int count) {} public String(byte bytes[], int offset, int length, String charsetName) {} //    ... 

この記事では、 Stringクラスの仕組みを理解しようとする代わりに、その機能とコードでの使用方法を理解するのに役立ちます。


文字列プールとは何ですか?


Stringクラスは、おそらくJavaで最も一般的に使用されるクラスです。 Stringを使用するたびに動的メモリ(メモリヒープ)に新しいオブジェクトを作成すると、大量のメモリが無駄になります。 文字列プールは、各行の値に対して1つのオブジェクトのみを保存することでこの問題を解決します。


文字列プールの文字列


行プールの行


DukeおよびJuggyを使用していくつかのString変数を作成しましたが、2つのオブジェクトのみが作成され、動的メモリ(ヒープ)に格納されます。 証明については、次のコード例を参照してください。 (Javaでは、「 == 」演算子を使用して2つのオブジェクトを比較し、同じオブジェクトが同じかどうかを判断します。)


 String juggy = "Juggy"; String anotherJuggy = "Juggy"; System.out.println(juggy == anotherJuggy); 

2つのString変数が文字列プール内の同じオブジェクトを指しているため、このコードはtrueを返します。 それらの意味は同じです。


例外はnew演算子です。


このコードを見てください。前の例と似ていますが、違いがあります。


 String duke = new String("duke"); String anotherDuke = new String("duke"); System.out.println(duke == anotherDuke); 

前の例に基づいて、このコードはtrueを返すと思うかもしれませんが、そうではありません。 new演算子を追加すると、メモリに新しいStringオブジェクトが作成されます。 したがって、JVMは2つの異なるオブジェクトを作成します。


ネイティブメソッド

Javaのネイティブメソッドは、通常、メモリの管理とパフォーマンスの最適化を目的として、C言語を使用してコンパイルされるメソッドです。

文字列プールとintern()メソッド


プールに文字列を格納するには、文字列インターンと呼ばれるメソッドが使用されます。


Javadocintern()メソッドについて教えてくれるのは次のとおりです。


  /** *      . * *   ( )   {@code String}. * *    intern,     , *    {@code String},   *  {@link #equals(Object)},     . * ,   {@code String}   *        {@code String}. * *   ,      {@code s}  {@code t}, * {@code s.intern() == t.intern()}  {@code true} *    ,  {@code s.equals(t)}  {@code true}. * *       . *      3.10.5 The Java™ Language Specification. * * @returns ,         , * , ,       . * * @jls 3.10.5 String Literals */ public native String intern(); 

intern()メソッドは、文字列プールに文字列を格納するために使用されます。 最初に、既存の行がプールに存在するかどうかを確認します。 そうでない場合は、プールに新しい行を作成します。 行プールのロジックは、 Flyweightパターンに基づいています。


次に、 newを使用して2行を作成するとどうなるかを確認します。


 String duke = new String("duke"); String duke2 = new String("duke"); System.out.println(duke == duke2); //    false System.out.println(duke.intern() == duke2.intern()); //    true 

newキーワードを使用した前の例とは異なり、この場合、比較はtrueを返しtrue 。 これは、 intern()メソッドを使用すると、文字列がプール内にあることが保証されるためです。


Stringクラスのequalsメソッド


equals()メソッドは、2つのクラスが同じかどうかを確認するために使用されます。 equals()Objectクラスに配置されるため、すべてのJavaクラスがそれを継承します。 ただし、 equals()メソッドは、正しく機能するためにオーバーライドする必要があります。 もちろん、 String equals()オーバーライドします。


ご覧ください:


 public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String aString = (String)anObject; if (coder() == aString.coder()) { return isLatin1() ? StringLatin1.equals(value, aString.value) : StringUTF16.equals(value, aString.value); } } return false; } 

ご覧のとおり、 Stringクラスの値は、オブジェクト参照ではなくequals()を介して比較されます。 オブジェクトへの参照が異なっていても問題ありません。 条件が比較されます。


一般的なStringメソッド


文字列比較の問題を解決する前に知っておく必要があることがもう1つあります。


Stringクラスの最も一般的なメソッドを検討してください。


 //         trim() //     substring(int beginIndex, int endIndex) //    length() //  ,     replaceAll(String regex, String replacement) // ,     CharSequence   contains(CharSequences) 

文字列比較の問題を解決する


小さなパズルを解いて、 Stringクラスについて学んだことを確認しましょう。


このタスクでは、学習した概念を使用して複数の行を比較します。 以下のコードを見て、各変数result値を決定できますか?


 public class ComparisonStringChallenge { public static void main(String... doYourBest) { String result = ""; result += " powerfulCode ".trim() == "powerfulCode" ? "0" : "1"; result += "flexibleCode" == "flexibleCode" ? "2" : "3"; result += new String("doYourBest") == new String("doYourBest") ? "4" : "5"; result += new String("noBugsProject") .equals("noBugsProject") ? "6" : "7"; result += new String("breakYourLimits").intern() == new String("breakYourLimits").intern() ? "8" : "9"; System.out.println(result); } } 

結論はどうなりますか?



正解は記事の最後に記載されています。


今何が起こったの? String動作を理解する


最初の行には以下が表示されます。


 result += " powerfulCode ".trim() == "powerfulCode" ? "0" : "1"; 

この場合、 trim()メソッドがスペースを削除すると、 new演算子を使用してnew Stringが作成されるため、結果はfalseです。


次に見るもの:


 result += "flexibleCode" == "flexibleCode" ? "2" : "3"; 

ここには秘密はありません;行は行プールで同じです。 この比較はtrue返しtrue


次に、次のものがあります。


 result += new String("doYourBest") == new String("doYourBest") ? "4" : "5"; 

newを使用すると、2つの新しい行が作成され、それらの値が等しいかどうかは関係ありません。 この場合、値が同じであっても比較はfalseになりfalse


次:


 result += new String("noBugsProject") .equals("noBugsProject") ? "6" : "7"; 

equals()メソッドを使用したため、オブジェクトのインスタンスではなく、文字列値が比較されます。


この場合、値が比較されるため、異なるオブジェクトであるかどうかは関係ありません。 結果はtrueです。


最後に、次のものがあります。


 result += new String("breakYourLimits").intern() == new String("breakYourLimits").intern() ? "8" : "9"; 

前に見たように、 intern()メソッドは文字列を文字列プールに入れます。 両方の行が同じオブジェクトを指しているため、この場合はtrueです。


一般的な文字列エラー


特に線に同じ値が含まれている場合、2つの線が同じオブジェクトを指しているかどうかを判断するのは困難です。 文字列値が同じであっても、newを使用すると、常にメモリ内に新しいオブジェクトが作成されることに注意してください。


Stringメソッドを使用してオブジェクト参照を比較することも難しい場合があります。 特異性は、メソッドが行の何かを変更すると、オブジェクトへの異なる参照が存在することです。


明確にするのに役立ついくつかの例:


 System.out.println("duke".trim() == "duke".trim()); 

trim()メソッドは新しい行を作成しないため、この比較は真になります。


 System.out.println(" duke".trim() == "duke".trim()); 

この場合、最初のtrim()メソッドは新しい行を生成します。メソッドがその仕事をするため、リンクが異なるためです。


最後に、 trim()が処理を行うと、新しい行が作成されます。


 //   trim   String new String(Arrays.copyOfRange(val, index, index + len), LATIN1); 

文字列について覚えておくべきこと



答え


この問題に対する答えはDです。結論は12568です。


続行するには...



Source: https://habr.com/ru/post/J428449/


All Articles