EN

Javaのプリミティブ型について

2018/5/13

==(同値)と.equals(等価)の違い

==はプリミティブ型の判定をするが、 .equalsはオブジェクトの参照先の中の値の判定をする。ここで、プリミティブ型の説明ができなかった。 ArrayListでよくintIntegerを混合してたり、intを使った際に ”ArrayListはプリミティブ型を使用出来ません”と、コンパイラに怒られてしまったり、 それで、とりあえずIntegerを使ってたという感じ。それで、プリミティブ型について詳しく調べてみた。

プリミティブ型とは

宣言のときに、メモリがあらかじめ決められていて、参照型よりメモリを節約できる型。要はプリミティブの方が参照型を使うより、 メモリを少なく節約出来る。

プリミティブ型の種類とメモリ量は以下の通り:

メモリ量(bytes)
byte1 bytes
boolean1 bytes
short2 bytes
char2 bytes
int4 bytes
float4 bytes
long8 bytes
double8 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で数値が 扱えるということ。

プリミティブ型とそのラッパーの対応表:

ラッパー
byteByte
booleanBoolean
shortShort
charCharacter
intInteger
floatFloat
longLong
doubleDouble

さいご

ここまでで、プリミティブ型に関してはわかったと思うけど、このプリミティブ型と参照型の違いから値渡しとか参照渡しとかの 話が出てきたりしてて、その理解にもつながったのでよかった。
それにJavaには値渡ししかなく、参照渡し(正確には参照の値渡し?らしい)なんてない。

Home