==(同値)と.equals(等価)の違い
==はプリミティブ型の判定をするが、
.equalsはオブジェクトの参照先の中の値の判定をする。ここで、プリミティブ型の説明ができなかった。
ArrayList
でよくint
とInteger
を混合してたり、int
を使った際に
”ArrayList
はプリミティブ型を使用出来ません”と、コンパイラに怒られてしまったり、
それで、とりあえずInteger
を使ってたという感じ。それで、プリミティブ型について詳しく調べてみた。
プリミティブ型とは
宣言のときに、メモリがあらかじめ決められていて、参照型よりメモリを節約できる型。要はプリミティブの方が参照型を使うより、 メモリを少なく節約出来る。
プリミティブ型の種類とメモリ量は以下の通り:
型 | メモリ量(bytes) |
---|---|
byte | 1 bytes |
boolean | 1 bytes |
short | 2 bytes |
char | 2 bytes |
int | 4 bytes |
float | 4 bytes |
long | 8 bytes |
double | 8 bytes |
主題に戻って、==がプリミティブ型を判定するが、オブジェクト同士を
==で比較したときはどういう判定なのかというとオブジェクトの参照同士を比較しているということ。
例えば次のようなもの:
Integer a = new Integer(1);
Integer b = new Integer(1);
a = b;
if(a == b) ~~ // false
よくある例だけど、このif文の結果はfalseとなる。 これはプリミティブ型と違い、インスタンスするとメモリをインスタンスごとに作り、そこにたとえ同じ値を入れたとしても参照がそれぞれ異なるので、 当然、プリミティブ型のように直接値を入れている時と違い、==で参照型を 判定したときに、上の例だと結果としてfalseになる。
Stringの特殊性
少し疑問に思ったのが、普段プリミティブ型のように使っているStringの存在。実は次の例だと、判定はtrueになる。
String a = "abc";
String b = "abc";
if(a == b) ~~ // true
この反応がプリミティブ型であるかのような振る舞いをするのだが、これはしっかりとインスタンスを生成していて、 上の例のようなnewを書かない宣言をすると同じ参照をするようにコンパイル時に行われ、あたかも値を渡しているように見えるのだ。 値が同じように見えて、実は参照が同じになっているというね...
ラッパー
最初の話にArrayList
でプリミティブ型が使えないという話があったが、int
が使えないと
自然とInteger
を流れで使っていたが、int
のままではなく、なぜInteger
なのか?
それはまず、ArrayList
ではプリミティブ型を扱えないということ。そして、int
をクラスに当たるものがあり、
そのときに出てくるのがラッパー。ラッパーはプリミティブ型をクラスにしたもので、そのおかげで、数値をArrayList
で使いたいときにint
のラッパーであるInteger
を使うことで、ArrayList
で数値が
扱えるということ。
プリミティブ型とそのラッパーの対応表:
型 | ラッパー |
---|---|
byte | Byte |
boolean | Boolean |
short | Short |
char | Character |
int | Integer |
float | Float |
long | Long |
double | Double |
さいご
ここまでで、プリミティブ型に関してはわかったと思うけど、このプリミティブ型と参照型の違いから値渡しとか参照渡しとかの
話が出てきたりしてて、その理解にもつながったのでよかった。
それにJavaには値渡ししかなく、参照渡し(正確には参照の値渡し?らしい)なんてない。