2011年5月22日日曜日

C/C++プログラマのためのJava入門覚書(2/2)

続き


■Object

Java上で使うクラスは自作だろうとなんだろうと、すべて「Object」というクラスを暗黙のうちに継承している。いくつかの処理ではこのObjectクラスのメソッドが勝手に呼び出されており、僕らはその恩恵をうけている。お世話になっている(なる)のはだいたいこのあたり。

  • clone(): オブジェクトのコピーを作成する。ただし、Cloneableインターフェースを実装していないと(継承していないと)例外が飛ばされる
  • - toString (): オブジェクトの文字列表現を生成してString型で返す。Override可能。System.out.printlnに文字以外を突っ込んだ時に、よしなに表示してくれるのはこいつのおかげ。
  • - hashCode (): オブジェクトのハッシュコードを返す。ハッシュテーブルとかのデータ構造にオブジェクトをぶち込むとき、キーを作成してくれる。Overrideできるが非推奨。
  • - equals(): 同じオブジェクトであるかどうかを検査する。Overrideできるが、同値関係(反射性、対称性、推移性、整合性)をすべて満たす必要があり、意外と厄介。また、hashCodeが「等価なオブジェクトは同じハッシュコードを返す」という性質との整合性もとらないといけないので、基本非推奨。


■クラス変数の比較

クラス変数XとYがあった場合、JavaにおいてX == Yは参照先の比較(すなわちポインタの比較)をしているに過ぎない。各オブジェクト同士が等しいかどうかを検証するために、equals()というメソッドが全てのクラスの親であるObjectクラスに用意されており、こいつが適宜Overrideされている。ただし、OverrideをするときにはhashCode()メソッドとの整合性をとったり、同値関係が成り立つことを確認したりと結構面倒なので注意。したがって、クラス変数の比較に == を使うことは、ほとんどない(んじゃないかな)。ちなみにJavaは演算子のoverrideは許されていない。


一方、Stringにはちょっとした罠が用意されている。
String a = new String ("hoge");
String b = new String ("hoge");
とやって、(a == b)とすると、falseになる。これは参照しているオブジェクトが違うから当然だ。ところがどっこい
String a = "hoge";
String b = "hoge";
とやって、(a == b)とすると、trueと評価される。なぜか。


これは、"hoge"という同じ文字列定数がコードに出現した場合、javacが同じオブジェクトとして勝手に最適化するため、このようなややこしいことが起きる。ちなみにコードが最適化されると、
String tmp = new String ("hoge")
String a = tmp;
String b = tmp;
のように置換されているそうだ。さらに、
a += "mage";
などと、文字列を変更しようとした瞬間に、さらに別のオブジェクトに置き換えられているらしい。実にややこしい。


[参考] http://education.yachinco.net/tips/java/06/1.html

■配列の記述

配列の括弧はどちらでもOK
int [] a;
int a[];
は等価らしい。

[参考] http://msugai.fc2web.com/java/array2.html


ちなみに、Javaは new Hoge[10]; とやっても、nullの入った配列が生成されるだけで
各要素(中身)は個別に生成する必要がある。


■数値型あれこれ

  • 値あふれが起きると、C言語などと同様に値がひっくり返る(例:最大値 → 最小値)
  • 各プリミティブ型に対応するラップクラス (int v.s. Integer, long v.s. Longなどなど)がデフォルトで用意されている。文字列からの変換や最大値、最小値の定数提供などをしてくれるが、一文字間違えただけで大惨事になる可能性もある。
  • 精度が低い型から高い型への代入は可能。逆はコンパイルエラー。
int a = 1;
short b = 2;
a = b; // OK
b = a; // Compile error

0 件のコメント:

コメントを投稿