・はじめに
Java一年未満の方へ研修用
型、変数に関して少し掘り下げて紹介
・対象
・Java一年未満
・型
◆型とは
・データを扱うためにその種類に応じた型が決まっている。
その種類は、大きく分けてふたつある。プリミティブ型と参照型。
◆プリミティブ型
<特徴>
全て変数のサイズ(bit)が決まっている。
規定のサイズを超える値を格納することはできない。
メモリのスタック領域に値が入っている
<種類>
short、byte、long、int、double、float、char、boolean
データ型 | 表現できる値や範囲 | ビット |
---|---|---|
boolean | true,false | 1 |
byte | -128 ~ 127 の整数 | 8 |
char | \u0000 ~ \uFFFF のUnicode文字列 | 16 |
short | -32768 ~ 32767 の整数 | 16 |
int | -2147483648 ~ 2147483647 の整数 | 32 |
float | 実数(単精度不動小数点数) | 32 |
long | -9223372036854775808 ~ 9223372036854775807 の整数 | 64 |
double | 実数(倍精度不動小数点数) | 64 |
◆参照型
<特徴>
変数に格納されているのは「値」そのものではなく、
値がメモリのどこに格納されているかを示す「参照値」ということ。
中々、イメージするのが難しいですが、身近なところで言うと「ロッカーと鍵」
実際に値が格納されているのはロッカーの中で、変数はロッカーの番号が書いた鍵のイメージ
<種類>
・String、配列、List(コレクション)など
◆ラッパークラス
・参照型に分類される、プリミティブ型たちの進化系クラス
・それぞれのクラスに、便利なメソッドが用意されている(toStringなど)
・プリミティブ型っぽく振る舞うけど、中身はnullの可能性がある(なので、ヌルポに注意)
●プリミティブ型→ラッパークラスの対比表
プリミティブ型 | ラッパークラス |
---|---|
boolean | Boolean |
byte | Byte |
char | Char |
short | Short |
int | Integer |
float | Float |
long | Long |
double | Double |
※short、floatは一生使わないと思って良い。(私も今まで使ったことがない)
◆オートボクシング・アンボクシング
・暗黙的(自動)型変換のこと
オートボクシング:プリミティブ型からラッパークラスへの自動変換
アンボクシング :ラッパークラスからプリミティブクラスへの自動変換
コードだと以下のような感じ
// オートボクシング
int numInt = 10;
Integer numInteger = numInt;
// アンボクシング
Integer numInteger = new Integer(10);
int numInt = numInteger;
※注意点
意図しない型変換が行われる可能性があり、無駄な処理となる場合があるため、型変換は明示的に行うこと。
// オートボクシング
int numInt = 10;
Integer numInteger = new Integer(numInt);
// または以下
Integer numInteger = Integer.valueOf(numInt);
// アンボクシング
Integer numInteger = new Integer(10);
int numInt = numInteger.intValue();
またラッパークラスは参照型のため、nullが入る可能性があります。
nullが入ったラッパークラスオブジェクトをアンボクシング機能を使ってプリミティブ型へ変換するとNullPointerExceptionが発生します。
Integer numInteger = null;
int numInt = numInteger; //★実行時にNullPointerException発生
オートボクシング・アンボクシングは一見便利に見える機能ですが、上記のことから思わぬバグを混入させる原因となる可能性があります。
個人的には非推奨です。(明示的型変換をしましょう)
・プリミティブ型と参照型のメモリ確保の違い
プリミティブ型の場合
int num1 = 100;
System.out.println(num1); // 100
変数をコンソールに出力すると100と表示されます。
プリミティブ型は実際の値が変数に格納されるのでメモリ上のイメージは以下になります。
変数を宣言するとメモリのスタック領域という場所に100が格納されます。
参照型の場合
int[] arr1 = {1,2,3};
System.out.println(arr1); // [I@9a53e913
変数をコンソールに出力するとなんだかよくわらない文字列が表示されます。
@以降が参照値と言われるものです。
参照型は参照値が変数に格納されているのでメモリ上のイメージは以下になります。
スタック領域には、参照値(9a53e913)が格納され、実際の値はヒープ領域に格納される。
スタック領域とヒープ領域
スタック領域:プリミティブ型の値と、参照型の参照値が保存される
ヒープ領域 :参照型の値が保存される
ヒープ領域にはオブジェクトのインスタンス、実際の値や、メソッドが格納されます。
メソッドの中で宣言された変数(ローカル変数)は全てスタック領域に格納されます。
処理が終わると、格納していた値は破棄されます。
少しややこしいですが
まずは、型によってメモリの使い方が違うのだなと認識しておくこと。