はじめに

Javaでプログラムを書く際、最も基本となるのが「変数」と「データ型」の理解です。変数はデータを格納する箱であり、データ型はその箱に入れられるデータの種類を決定します。Javaは静的型付け言語であり、すべての変数は使用前に型を宣言する必要があります。

この記事では、Javaの8つのプリミティブ型と参照型の違い、変数の宣言・初期化、型変換、そしてJava 10以降で導入されたvarによる型推論まで、段階的に解説します。

変数の宣言と初期化

変数を使用するには、まず「宣言」と「初期化」が必要です。

変数の宣言

変数の宣言は、型と変数名を指定して行います。

1
2
3
4
// 変数の宣言
int age;
String name;
double price;

変数の初期化

宣言した変数に値を代入することを「初期化」と呼びます。

1
2
3
4
5
6
7
// 宣言と初期化を分ける
int age;
age = 25;

// 宣言と初期化を同時に行う(推奨)
int score = 100;
String message = "Hello, Java!";

変数の命名規則

Javaでは変数名に関して以下のルールがあります。

ルール
先頭は英字、_(アンダースコア)、$のいずれか _count$valuename
2文字目以降は数字も使用可能 item1price2
予約語は使用不可 intclassforなどは使えない
大文字と小文字は区別される Namenameは別の変数

慣例として、変数名はキャメルケースfirstNametotalAmount)で記述します。

8つのプリミティブ型を理解する

Javaには8つのプリミティブ型(基本データ型)があります。これらはJVM(Java仮想マシン)に組み込まれた型であり、オブジェクトではありません。

整数型

整数を扱う型は4種類あり、それぞれ格納できる値の範囲が異なります。

サイズ 最小値 最大値 用途
byte 8ビット -128 127 メモリ節約が必要な場合
short 16ビット -32,768 32,767 メモリ節約が必要な場合
int 32ビット -2,147,483,648 2,147,483,647 一般的な整数(デフォルト)
long 64ビット -9,223,372,036,854,775,808 9,223,372,036,854,775,807 大きな整数値
1
2
3
4
byte smallNumber = 100;
short mediumNumber = 10000;
int regularNumber = 1000000;
long bigNumber = 9223372036854775807L; // Lサフィックスが必要

long型のリテラルには末尾にL(またはl)を付ける必要があります。小文字のlは数字の1と紛らわしいため、大文字のLを使用することが推奨されます。

浮動小数点型

小数を扱う型は2種類あります。

サイズ 精度 用途
float 32ビット 約7桁 メモリ節約が必要な場合
double 64ビット 約15桁 一般的な小数(デフォルト)
1
2
3
float temperature = 36.5f;  // fサフィックスが必要
double pi = 3.141592653589793;
double scientific = 1.234e2; // 科学表記(= 123.4)

金融計算など高精度が必要な場合は、floatdoubleではなくjava.math.BigDecimalクラスを使用してください。浮動小数点型は2進数で表現されるため、10進数の正確な表現ができない場合があります。

文字型

char型は1つのUnicode文字(16ビット)を格納します。

1
2
3
char letter = 'A';
char japaneseChar = 'あ';
char unicodeChar = '\u0041'; // Unicodeエスケープ(= 'A')

シングルクォート(')で囲むことに注意してください。ダブルクォート(")はString型用です。

論理型

boolean型はtrueまたはfalseの2値のみを持ちます。

1
2
3
boolean isActive = true;
boolean hasPermission = false;
boolean isAdult = age >= 18; // 比較演算の結果

プリミティブ型の一覧とデフォルト値

フィールド(クラス変数・インスタンス変数)として宣言された場合、プリミティブ型には以下のデフォルト値が設定されます。

デフォルト値
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char ‘\u0000’(null文字)
boolean false

ローカル変数にはデフォルト値が設定されないため、使用前に必ず初期化する必要があります。

数値リテラルの便利な記法

Java 7以降では、数値リテラルにアンダースコア(_)を挿入して読みやすくできます。

1
2
3
4
long creditCard = 1234_5678_9012_3456L;
int million = 1_000_000;
int binary = 0b1010_1100; // 2進数表記
int hex = 0xFF_EC_DE_5E;  // 16進数表記

参照型とは何か

参照型は、オブジェクトへの「参照(メモリアドレス)」を格納する型です。プリミティブ型が値そのものを格納するのに対し、参照型はオブジェクトが格納されているメモリ上の場所を指し示します。

プリミティブ型と参照型の違い

以下の図は、プリミティブ型と参照型のメモリ上での違いを示しています。

graph LR
    subgraph "プリミティブ型"
        A["変数 age"] --> B["値: 25"]
    end
    subgraph "参照型"
        C["変数 person"] --> D["参照(アドレス)"]
        D --> E["Personオブジェクト<br/>name: 'Taro'<br/>age: 25"]
    end

代表的な参照型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// String(文字列)
String greeting = "Hello, World!";

// 配列
int[] numbers = {1, 2, 3, 4, 5};

// クラスのインスタンス
List<String> names = new ArrayList<>();

// null(何も参照していない状態)
String empty = null;

参照型の特徴

参照型には以下の特徴があります。

  1. nullを代入可能: 参照型の変数にはnullを代入でき、「何も参照していない」状態を表現できます
  2. メソッドを持つ: オブジェクトはメソッドを持ち、操作を行えます
  3. ヒープメモリに格納: オブジェクト本体はヒープ領域に格納されます
1
2
3
String text = "Java Programming";
int length = text.length();      // メソッド呼び出し
String upper = text.toUpperCase(); // "JAVA PROGRAMMING"

ラッパークラス

各プリミティブ型には対応するラッパークラスがあります。これにより、プリミティブ値をオブジェクトとして扱えます。

プリミティブ型 ラッパークラス
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
1
2
3
4
5
6
7
// オートボクシング(自動変換)
Integer boxedInt = 100;        // int → Integer
int unboxedInt = boxedInt;     // Integer → int

// ラッパークラスのメソッド
int parsed = Integer.parseInt("123");
String binary = Integer.toBinaryString(10); // "1010"

型変換(暗黙的変換と明示的キャスト)

異なる型の間で値を変換する必要がある場合があります。Javaには2種類の型変換があります。

暗黙的変換(拡大変換)

小さい型から大きい型への変換は自動的に行われます。データの損失がないため、コンパイラが自動で変換します。

graph LR
    A[byte] --> B[short]
    B --> C[int]
    C --> D[long]
    D --> E[float]
    E --> F[double]
    G[char] --> C
1
2
3
4
5
6
int intValue = 100;
long longValue = intValue;    // int → long(自動変換)
double doubleValue = longValue; // long → double(自動変換)

byte b = 10;
int i = b;  // byte → int(自動変換)

明示的キャスト(縮小変換)

大きい型から小さい型への変換は、データの損失が発生する可能性があるため、明示的なキャストが必要です。

1
2
3
4
5
6
7
8
double pi = 3.14159;
int truncated = (int) pi;  // 3(小数部分が切り捨てられる)

long bigValue = 1000L;
int smallValue = (int) bigValue; // 明示的キャストが必要

int large = 130;
byte small = (byte) large; // -126(オーバーフロー発生)

キャスト時にオーバーフローが発生すると、予期しない値になることがあります。キャストを行う前に値の範囲を確認することが重要です。

文字列との変換

プリミティブ型と文字列の相互変換は頻繁に行われます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// プリミティブ型 → 文字列
String strInt = String.valueOf(123);
String strDouble = String.valueOf(3.14);
String strBool = String.valueOf(true);

// 文字列連結による変換
String result = "" + 100; // "100"

// 文字列 → プリミティブ型
int parsedInt = Integer.parseInt("123");
double parsedDouble = Double.parseDouble("3.14");
boolean parsedBool = Boolean.parseBoolean("true");

varによるローカル変数型推論(Java 10以降)

Java 10で導入されたvarキーワードを使用すると、コンパイラが右辺の値から型を推論してくれます。

varの基本的な使い方

1
2
3
4
5
6
7
8
9
// 従来の書き方
String message = "Hello, Java!";
ArrayList<String> names = new ArrayList<String>();

// varを使用した書き方
var message = "Hello, Java!";       // String型と推論
var names = new ArrayList<String>(); // ArrayList<String>型と推論
var count = 100;                    // int型と推論
var pi = 3.14;                      // double型と推論

varの使用条件と制限

varは以下の条件で使用できます。

使用可能 使用不可
ローカル変数 フィールド(インスタンス変数)
forループの変数 メソッドの引数
try-with-resourcesの変数 メソッドの戻り値型
初期化なしの宣言
nullでの初期化
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// 使用可能な例
var items = List.of("A", "B", "C");
for (var item : items) {
    System.out.println(item);
}

for (var i = 0; i < 10; i++) {
    System.out.println(i);
}

try (var reader = new BufferedReader(new FileReader("file.txt"))) {
    var line = reader.readLine();
}

// コンパイルエラーになる例
var value;           // 初期化が必要
var nothing = null;  // nullからは型を推論できない

varを使うべき場面

varは可読性を高める場面で使用し、型が不明確になる場面では避けることが推奨されます。

1
2
3
4
5
6
7
// 推奨:右辺から型が明確な場合
var users = new HashMap<String, List<User>>();
var config = ConfigurationFactory.createDefault();

// 非推奨:型が不明確になる場合
var result = service.process(data); // 戻り値の型が分かりにくい
var x = getValue();                  // 何が返るか分からない

定数の定義(final)

finalキーワードを使用すると、一度代入した値を変更できない定数を定義できます。

final変数の宣言

1
2
3
final int MAX_SIZE = 100;
final String APP_NAME = "MyApplication";
final double TAX_RATE = 0.10;

定数名は慣例として大文字のスネークケースMAX_SIZEDEFAULT_VALUE)で記述します。

finalの使用場面

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class Constants {
    // クラス定数(static final)
    public static final int MAX_USERS = 1000;
    public static final String VERSION = "1.0.0";
    
    // インスタンス定数
    private final String id;
    
    public Constants(String id) {
        this.id = id; // コンストラクタで初期化可能
    }
}

final参照型の注意点

finalで宣言した参照型は、参照先の変更は禁止されますが、オブジェクトの内容は変更可能です。

1
2
3
4
5
final List<String> names = new ArrayList<>();
names.add("Taro");    // オブジェクトの内容変更は可能
names.add("Hanako");  // 可能

// names = new ArrayList<>(); // コンパイルエラー:参照先の変更は不可

よくあるエラーと対処法

Java初心者がつまずきやすいエラーと対処法を紹介します。

変数の未初期化エラー

ローカル変数を初期化せずに使用するとコンパイルエラーになります。

1
2
3
4
5
6
7
// エラー例
int count;
System.out.println(count); // コンパイルエラー:変数countは初期化されていない可能性があります

// 対処法
int count = 0;
System.out.println(count); // 正常に動作

型の不一致エラー

互換性のない型を代入しようとするとエラーになります。

1
2
3
4
5
// エラー例
int number = "100"; // コンパイルエラー:型の不一致

// 対処法
int number = Integer.parseInt("100"); // 文字列を数値に変換

オーバーフロー

型の範囲を超える値を格納しようとすると、予期しない結果になります。

1
2
3
4
5
6
// 問題のある例
int maxInt = Integer.MAX_VALUE; // 2147483647
int overflow = maxInt + 1;       // -2147483648(オーバーフロー)

// 対処法:より大きな型を使用
long safeValue = (long) maxInt + 1; // 2147483648

NullPointerException

参照型変数がnullの状態でメソッドを呼び出すと発生します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// エラー例
String text = null;
int length = text.length(); // NullPointerException

// 対処法:null チェックを行う
if (text != null) {
    int length = text.length();
}

// Java 14以降のOptional活用
Optional.ofNullable(text)
    .map(String::length)
    .ifPresent(System.out::println);

精度の損失警告

暗黙的な縮小変換はコンパイルエラーになります。

1
2
3
4
5
6
7
8
9
// エラー例
double pi = 3.14;
float f = pi; // コンパイルエラー:精度が失われる可能性があります

// 対処法:明示的キャスト
float f = (float) pi;

// または最初からfloatリテラルを使用
float f = 3.14f;

まとめ

この記事では、Javaの変数とデータ型について以下の内容を解説しました。

  • 変数の宣言と初期化:型と変数名を指定し、値を代入する基本構文
  • 8つのプリミティブ型:整数型(byte、short、int、long)、浮動小数点型(float、double)、文字型(char)、論理型(boolean)
  • 参照型:オブジェクトへの参照を格納し、nullを許容する型
  • 型変換:暗黙的変換(拡大変換)と明示的キャスト(縮小変換)
  • var:Java 10以降のローカル変数型推論
  • final:変更不可の定数定義

Javaの型システムを正しく理解することで、バグの少ない堅牢なコードを書けるようになります。次のステップとして、演算子と制御構文を学び、より複雑なプログラムロジックを構築していきましょう。

参考リンク