Javaでの文字列比較

Javaでは、Stringクラスはの配列をカプセル化しcharます。簡単にString言えば、単語、文、またはその他の必要なデータを構成するために使用される文字の配列です。

カプセル化は、オブジェクト指向プログラミングで最も強力な概念の1つです。カプセル化されているため、Stringクラスがどのように機能するを知る必要はありません。あなただけ知っている必要がありますどのような方法は、そのインターフェイス上で使用します。

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

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

カプセル化をよりよく理解するために、物理的なオブジェクト、つまり車について考えてみましょう。あなたはそれを運転するために車がボンネットの下でどのように機能するかを知る必要がありますか?もちろんそうではありませんが、アクセル、ブレーキ、ステアリングホイールなどの車のインターフェースが何をするのかを知る必要があります。これらの各インターフェースは、加速、ブレーキ、左折、右折などの特定のアクションをサポートしています。オブジェクト指向プログラミングでも同じです。

Java Challengersシリーズの最初のブログでは、メソッドのオーバーロードを紹介Stringしました。これは、クラスで広く使用されている手法です。オーバーロードは、次のようなクラスを非常に柔軟にすることができます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) {} // And so on…... 

むしろどのように理解しようとするよりもStringクラスが動作しますが、このJavaのチャレンジャーはあなたが理解するのに役立ちますどのようなそれがないと、どのようにあなたのコードでそれを使用します。

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

StringおそらくJavaで最も使用されているクラスです。を使用するたびにメモリヒープに新しいオブジェクトが作成されると、String大量のメモリが浪費されます。Stringプールごとにただ一つのオブジェクトを格納することによってこの問題を解決しString、以下に示すように、値。

ラファエル・チネラート・デル・ネロ

とsのString変数を作成しましたが、2つのオブジェクトのみが作成され、メモリヒープに格納されます。証拠として、次のコードサンプルを参照してください。(Javaの「」演算子は、2つのオブジェクトを比較し、それらが同じかどうかを判断するために使用されることを思い出してください。)DukeJuggyString==

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

true2つStringのsがStringプール内の同じオブジェクトを指しているため、このコードが返されます。それらの値は同じです。

例外:「新しい」演算子

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

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

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

ネイティブメソッド

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

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

をプールに格納するにStringは、インターンStringと呼ばれる手法を使用します。Javadocがメソッドについて教えてくれることは次のとおりです。Stringintern()

 /** * Returns a canonical representation for the string object. * * A pool of strings, initially empty, is maintained privately by the * class {@code String}. * * When the intern method is invoked, if the pool already contains a * string equal to this {@code String} object as determined by * the {@link #equals(Object)} method, then the string from the pool is * returned. Otherwise, this {@code String} object is added to the * pool and a reference to this {@code String} object is returned. * * It follows that for any two strings {@code s} and {@code t}, * {@code s.intern() == t.intern()} is {@code true} * if and only if {@code s.equals(t)} is {@code true}. * * All literal strings and string-valued constant expressions are * interned. String literals are defined in section 3.10.5 of the * The Java™ Language Specification. * * @returns a string that has the same contents as this string, but is * guaranteed to be from a pool of unique strings. * @jls 3.10.5 String Literals */ public native String intern(); 

このintern()メソッドはString、をStringプールに格納するために使用されます。まず、String作成したものがすでにプールに存在するかどうかを確認します。そうでない場合は、Stringプールに新しいものを作成します。舞台裏では、StringプーリングのロジックはFlyweightパターンに基づいています。

ここで、newキーワードを使用して2つStringのsを強制的に作成するとどうなるかに注目してください。

 String duke = new String("duke"); String duke2 = new String("duke"); System.out.println(duke == duke2); // The result will be false here System.out.println(duke.intern() == duke2.intern()); // The result will be true here 

newキーワードを使用した前の例とは異なり、この場合、比較は真であることがわかります。これintern()は、このメソッドを使用Stringすると、がプールに確実に保存されるためです。

StringクラスのEqualsメソッド

このequals()メソッドは、2つのJavaクラスの状態が同じであるかどうかを確認するために使用されます。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が比較されます。

最も一般的な文字列メソッド

String比較に挑戦する前に知っておく必要がある最後のことが1つだけあります。Stringクラスの次の一般的なメソッドを検討してください。

 // Removes spaces from the borders trim() // Gets a substring by indexes substring(int beginIndex, int endIndex) // Returns the characters length of the String length() // Replaces String, regex can be used. replaceAll(String regex, String replacement) // Verifies if there is a specified CharSequence in the String contains(CharSequences) 

文字列比較に挑戦してください!

Stringクラスについて学んだことを簡単なチャレンジで試してみましょう。

この課題では、String私たちが調査した概念を使用して、いくつかのを比較します。以下のコードを見て、各結果変数の最終値を決定できますか?

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

結果変数の最終値を表す出力はどれですか?

A:02468

B:12469

C:12579

D:12568

ここであなたの答えを確認してください。

今何があったの?文字列の動作を理解する

コードの最初の行には、次のように表示されます。

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

String後に同じになるtrim()メソッドが呼び出され、String“ powerfulcode “初めに異なっていました。この場合、比較はですfalsetrim()メソッドが境界からスペースを削除するStringと、new演算子を使用してnewを強制的に作成するためです。

次に、次のように表示されます。

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

No mystery here, the Strings are the same in the String pool. This comparison returns true.

Next, we have:

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

Using the new reserved keyword forces the creation of two new Strings, whether they are equal or not. In this case the comparison will be false even if the String values are the same.

Next is:

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

Because we’ve used the equals() method, the value of the String will be compared and not the object instance. In that case, it doesn’t matter if the objects are different because the value is being compared. This comparison returns true.

Finally, we have:

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

As you’ve seen before, the intern() method puts the String in the String pool. Both Strings point to the same object, so in this case the comparison is true.

Video challenge! Debugging String comparisons

Debugging is one of the easiest ways to fully absorb programming concepts while also improving your code. In this video you can follow along while I debug and explain the Java Strings challenge:

Common mistakes with Strings

It can be difficult to know if two Strings are pointing to the same object, especially when the Strings contain the same value. It helps to remember that using the reserved keyword new always results in a new object being created in memory, even if the values are the same.

Using String methods to compare Object references can also be tricky. The key is, if the method changes something in the String, the object references will be different.

A few examples to help clarify:

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

This comparison will be true because the trim() method does not generate a new String.

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

In this case, the first trim() method will generate a new String because the method will execute its action, so the references will be different.

Finally, when trim() executes its action, it creates a new String:

 // Implementation of the trim method in the String class new String(Arrays.copyOfRange(val, index, index + len), LATIN1); 

What to remember about Strings

  • Strings are immutable, so a String’s state can’t be changed.
  • To conserve memory, the JVM keeps Strings in a String pool. When a new String is created, the JVM checks its value and points it to an existing object. If there is no String with that value in the pool, then the JVM creates a new String.
  • ==演算子を使用して、オブジェクト参照を比較します。このequals()メソッドを使用すると、の値が比較されますString。同じルールがすべてのオブジェクトに適用されます。
  • new演算子を使用すると、同じ値のが存在する場合でもStringStringプールに新しいものが作成されStringます。

 

解答

このJavaチャレンジャーへの答えはオプションD12568です。出力はになります。

このストーリー「Javaでの文字列比較」は、もともとJavaWorldによって公開されました。