2つのファミリー:プリミティブと参照
Javaのすべての値には型があり、その型は2つのファミリーのどちらかに属します。プリミティブ型は生の値を直接保持します - 数値、1文字、または真/偽です。参照型は、メモリ上の別の場所にあるオブジェクトへの参照(ポインタ)を保持します:String、配列、そしてあなたやライブラリが定義するすべてのクラスです。
この区別が重要なのは、プリミティブは軽量で値としてコピーされるのに対し、参照変数は共有オブジェクトを指すからです。まずは8つのプリミティブから始めましょう - これらは他のすべてが構築される土台です。
8つのプリミティブ型
Javaには厳密に8つの組み込みプリミティブ型があります。6つは数値、1つは文字、1つは真偽値です:
最初に気づいておきたい点がいくつかあります:2_000_000 のアンダースコアはコンパイラが無視する単なる視覚的な区切りであること、L と f の接尾辞は必須であること(詳しくは後述)、そして char はシングルクォートを使い、String ならダブルクォートを使うことです。
数値型の選び方
byte や short はほとんど必要ありません - これらは巨大な配列でのみメモリを節約します。実際の判断は、整数なら int/long、小数なら float/double の間で行われます。
| 型 | サイズ | 使う場面 |
|---|---|---|
int | 32ビット | 整数のデフォルト(最大約21億まで) |
long | 64ビット | 約20億を超える値:ミリ秒のタイムスタンプ、ファイルサイズ |
double | 64ビット | 小数のデフォルト - 良好な精度 |
float | 32ビット | メモリが逼迫していて精度を犠牲にできる場合のみ |
落とし穴はオーバーフローです。int は範囲を超えると静かに一巡します - エラーは出ず、ただ間違った答えになるだけです:
maxInt + 1 が -2147483648 にオーバーフローするのは、両方のオペランドが int であり、結果も int のままだからです。先に一方を long にキャストすると、計算は64ビットで行われます。値が大きくなり得るとき - 特に1970年からのミリ秒 - は long を使いましょう。
リテラルとその接尾辞
そのままの数値リテラルにはデフォルトの型があり、これが人を悩ませます。100 は int、3.14 は double です。long や float のリテラルを書くには接尾辞を付けなければなりません:
8_000_000_000L から L を外すと、リテラルが long 変数に届く前に int の範囲を超えるため、コードはコンパイルできません。0.5f から f を外すと、Javaは double をキャストなしに float へ代入できないと文句を言います。接尾辞は大文字小文字を区別しませんが、大文字の L を使いましょう - 小文字の l は数字の 1 とそっくりに見えます。
char は数値の変装である
char は16ビットのUnicodeコードユニットを格納します。つまり、小さな符号なし整数としても振る舞います。算術演算を行ったり、キャストで相互に変換したりできます:
これは文字をずらすのにたまに便利ですが、テキスト処理をこれに頼ってはいけません - そのためにあるのが String です。char はシングルクォート('A')を使うことに注意してください。ダブルクォート("A")は1文字の String を作り、これはまったく別の型です。
デフォルト値(とローカル変数の落とし穴)
初期化しなかったフィールドや配列の要素には、妥当なデフォルト値が与えられます。しかしこれはフィールドと配列のスロットにのみ当てはまります - ローカル変数にはデフォルト値が一切与えられず、値を代入する前に使うのは実行時のサプライズではなくコンパイルエラーになります。
もし代わりに main の中で int x; System.out.println(x); と書いたら、コンパイラは「variable x might not have been initialized」と言ってこれを拒否します。この厳格さは利点です - ゴミを読み取るのを防いでくれます。覚えておくべきデフォルト値:数値型は 0、boolean は false、char は ' '、そしてあらゆる参照型は null です。
次は:Strings
String は、あなたが最もよく扱う参照型です - テキスト、連結した値、ユーザー入力。ここで扱ったプリミティブとは違う振る舞いをします:オブジェクトであり、不変(immutable)であり、文字列の比較には独自の落とし穴があります。次のページで取り上げます。
よくある質問
Javaにはデータ型がいくつありますか?
Javaには8つのプリミティブ型があります:byte、short、int、long、float、double、char、boolean です。それ以外のすべて - String、配列、あらゆるオブジェクト - は参照型です。したがって組み込みプリミティブの数は8つで固定ですが、参照型は無制限です。なぜなら、あなた(やライブラリ)が新しいクラスを定義するからです。
Javaにおけるintとlongの違いは何ですか?
どちらも整数を保持しますが、int は32ビット(範囲は約±21億)、long は64ビット(範囲は約±920京)です。デフォルトでは int を使い、値が20億を超える可能性がある場合は long に切り替えます - ミリ秒単位のタイムスタンプ、ファイルサイズ、大きなカウンタなどです。long リテラルには L 接尾辞が必要です。例:long big = 10000000000L;。
Javaにおけるintのデフォルト値は何ですか?
int のフィールドはデフォルトで 0 になります - ただしデフォルト値が与えられるのはフィールドと配列の要素だけです。long は 0L、double は 0.0、boolean は false、char は '\u0000'、そしてあらゆる参照型は null になります。ローカル変数にはデフォルト値が一切与えられません - 使う前に値を代入しなければならず、そうしないとコードはコンパイルできません。