1. 比較
プログラマーは、常に異なる変数を相互に比較する必要があります。しかし、すでに見たように、すべてはそれほど単純ではありません。
整数の比較は非常に簡単です。使用するだけで==
完了です。実数を比較するには、その差 (またはむしろ差の絶対値) を非常に小さな数値と比較する必要があります。
文字列の比較はさらに困難です。何よりも、これは文字列がオブジェクトであるためです。さらに、プログラマは、状況に応じて文字列の比較を少し異なる方法で行うことを望むことがよくあります。
2. 文字列のメモリ配置方法
すでに見たように、文字列は整数や実数とは異なる方法でメモリに保存されます。
文字列の保存には 2 つのメモリ ブロックが使用されます。1 つのブロックにはテキストそのもの (サイズはテキストのサイズによって異なります) が保存され、2 番目のブロック (4 バイト) には最初のブロックのアドレスが保存されます。
経験豊富なプログラマは次のように言うでしょうが、「String
str
変数にはオブジェクトへの参照が格納されていますString
。
3. 文字列への参照の割り当て
このアプローチの利点は、ある文字列変数を別の文字列変数に割り当てる必要がある場合に明らかになります。例:
String text = "This is a very important message";
String message = text;
結果としてメモリに含まれる内容は次のとおりです。
このタイプの代入操作の後、String
オブジェクトは元の場所に残り、そのアドレス (オブジェクトへの参照) だけが変数にコピーされますmessage
。
4. 参照とオブジェクトの操作
しかし、文字列を大文字 (大文字) に変換すると決めた場合、Java マシンはすべてを正しく実行します。最終的に 2 つのオブジェクトが作成され、 変数String
とtext
変数message
にはそれぞれ独自のオブジェクトへの参照が格納されます。
例:
String text = "This is a very important message";
String message = text.toUpperCase();
結果としてメモリに含まれる内容は次のとおりです。
このtoUpperCase()
メソッドは呼び出される文字列を変更しないことに注意してください。代わりに、新しい文字列 (新しいオブジェクト) を作成し、それへの参照を返します。
さらに興味深い例はどうでしょうか。文字列をオブジェクトに渡すことにしたとしますScanner
(文字列から値を読み取るため)。
例:
String text = "10 20 40 80";
Scanner console = new Scanner(text);
int a = console.nextInt();
int b = console.nextInt();
Scanner
クラスの仕組みについて詳しくは、こちらをご覧ください。
すべてがメモリにどのように保存されるかは次のとおりです。
この場合、単一のString
オブジェクトがそのままメモリ内に残り、そのオブジェクトへの参照のみが渡され、変数に格納されます。
String
5.オブジェクトへの参照の比較
そしてついに、楽しい部分である文字列比較に到達しました。
==
文字列変数の比較に使用できる演算子は、 (等しい) と!=
(等しくない)の 2 つです。「より大きい」、「より小さい」、または「以上」演算子は使用できません。コンパイラはそれを許可しません。
しかし、ここには興味深いニュアンスがあります。文字列変数には実際に何が格納されるのでしょうか? そうです、オブジェクトへのアドレス (参照) です。そして、比較されるのは次のアドレスです。
String text = "Hi";
String message = text;
String s1 = text.toUpperCase();
String s2 = text.toUpperCase();
メモリに残る内容は次のとおりです。
変数message
とtext
変数は同じオブジェクトを参照します (アドレスを格納します)。ただし、s1
およびs2
変数には、非常に似ているが異なるオブジェクトへの参照が格納されます。
コード内でこれら 4 つの変数を比較すると、次の結果が得られます。
コード | コンソール出力 |
---|---|
|
|
GO TO FULL VERSION