CodeGym /コース /JAVA 25 SELF /Javaにおける型推論と定数

Javaにおける型推論と定数

JAVA 25 SELF
レベル 10 , レッスン 2
使用可能

1. キーワード var

Java でコードを書き始めると、厳密な型システムに出会います。各変数は明示的に宣言し、型を指定しなければなりません。これは信頼性のために有用ですが、時に記述が冗長になりコードを読みづらくします。そこで開発を楽にするために、Java には便利な仕組み — 型推論(var が加わりました。

var を使うと、型安全性を損なうことなく、より短くクリーンなコードが書けます。右辺に値を書けば、コンパイラが型を推論してくれます。

var age = 23;            // コンパイラが 23 の型を推論し、int age を挿入する
var name = "Anna";       // コンパイラが "Anna" の型を推論し、String name を挿入する
var price = 99.99;       // コンパイラが 99.99 の型を推論し、double price を挿入する

なぜ var が導入されたのか?

  • 読みやすさ: HashMap<String, List<Integer>> のような長い型を手で書く必要がありません。
  • 柔軟性: 右辺を変更すれば、左辺の var は自動で追随します。
  • 現代的なスタイル: 初期化から型が容易に読み取れる箇所では、ほとんどの現代的な Java プロジェクトが var を使用しています。

var を使ってよい(推奨される)場面

  • 右辺から変数の型が一意に分かるとき。
  • 型が明らかなとき(var price = 100; — これは int と分かる)。
  • 型が長すぎる・複雑なとき(例: HashMap<Integer, List<Calendar>>)。

配列の例

var numbers = new int[] { 1, 2, 3, 4 };

メソッドの例

var input = console.nextLine(); // input は String(メソッドは String を返す)

var を使わない方がよい場合

右辺から型が明確でないと、コードの可読性が下がることがあります。1か月後に自分で見返して型が分からないようなら、明示的に書いた方がよいでしょう。

var mystery = DoSomethingVeryComplicated(); // これは何の型だ、mystery???

ここでは明示的に型を書くのがよいでしょう:

String result = DoSomethingVeryComplicated();

黄金律: var は可読性を損なわないところだけで使う!

var はローカル変数専用

キーワード var はメソッド内のローカル変数でのみ使えます。次の用途では使えません:

  • メソッドのパラメータ;
  • クラスのフィールド;
  • 定数。

var の仕組み(内部的には)

  • コンパイル時に Java コンパイラが正しい型を挿入します。
  • コンパイル後、var は存在しません。
  • 性能低下はありません。あくまでプログラマのための記述上の利便性です。
var year = 2025; // コンパイル時には次のようになる: int year = 2025;

var の典型的な誤り

初期化していない変数:

var a; // エラー: 型を推論する材料がありません!

あいまいな初期化:

var list = null; // エラー: null の型は定義できません!

異なる型での再利用:

var value = 5;     // value は int
value = "Five";    // エラー: value はすでに int です!

比較: 明示的な型と var

シナリオ 明示的な型 var
型が明確
int age = 42;
var age = 42;
メソッドが複雑な型を返す
HashMap<Integer, String> dict = SomeFunc();
var dict = SomeFunc();
配列
String[] names = ...
var names = ...
ヒント
現代のプロジェクトでは、ローカル変数に対しては多くの場合 var が使われます。パラメータ、フィールド、定数には明示的な型を使いましょう。

2. キーワード final: 定数の宣言

定数とは、初期化後に値を変更できない変数です。定数はコードを堅牢かつ分かりやすくし、重要な数値や文字列の偶発的な変更から守ってくれます。

  • 円周率(PI = 3.14159…)
  • 最大ユーザー数(MAX_USERS = 1000
  • 会社名(COMPANY_NAME = "CodeGym"

Java では定数の宣言に final 修飾子を使います。コンパイラに「最初の代入以降は変更不可!」と伝えるものです。


final Tip IMYA_KONSTANTY = znachenie;
Java における定数宣言の構文

構文

final int DAYS_IN_WEEK = 7;
final double PI = 3.1415926535;
final String GREETING = "こんにちは、Java!";

重要なポイント:

  • final の変数は必ず初期化が必要です(クラスのフィールドであれば、フィールド初期化子やコンストラクタで)。
  • 値を変更しようとするとコンパイルエラーになります。

例: final 変数は変更できない

final int MAX_USERS = 100;
MAX_USERS = 200; // エラー: final 変数に新しい値は代入できません

補足: 代入をコメントアウト解除すると、プロジェクトはビルドに失敗します。

3. static final: クラスレベルの定数

Java では、特定のオブジェクトに依存しない「クラス全体で共有する」定数がよく必要になります。そのために static + final の組み合わせを使います。

なぜ static final なのか?

  • static — 変数はクラスに属し(全インスタンスで 1 つ)。
  • final — 値は変更できません。

構文

public static final double PI = 3.1415926535;
public static final int MAX_USERS = 1000;
public static final String COMPANY_NAME = "CodeGym";

どこに宣言する? 通常はクラスの先頭(メソッドより前)に置きます。

クラス内での使用例

public class MathUtils 
{
    public static final double PI = 3.1415926535;

    public static double circleLength(double radius) 
    {
        return 2 * PI * radius;
    }
}

呼び出し:

double len = MathUtils.circleLength(5);
System.out.println(len); // 31.4159...

注意: 定数にはクラス名経由でアクセスします: MathUtils.PI

4. 単なる finalstatic final の違い

final — フィールドは初期化後に値を変更できませんが、各オブジェクトごとに値を持ちます。

static final — クラス全体で 1 つの定数であり、オブジェクトには依存しません。

実例: 違いを確認

public class User 
{
    public final String name;                      // 各 User が独自の名前を持つ(final)
    public static final String COMPANY = "CodeGym"; // 全員で共有される 1 つの会社名(static final)

    public User(String name) 
    {
        this.name = name;
    }
}
User u1 = new User("Vasya");
User u2 = new User("Petya");

System.out.println(u1.name);      // Vasya
System.out.println(u2.name);      // Petya
System.out.println(User.COMPANY); // CodeGym

結論: name は各インスタンス固有の不変フィールド、COMPANY は共有の定数です。

定数の命名規約

定数名は大文字+アンダースコア(UPPER_SNAKE_CASE)で記述するのが慣例です。

public static final int MAX_USERS = 1000;
public static final double GRAVITY = 9.81;
public static final String DEFAULT_GREETING = "Hello, world!";

ヒント: このような名前を見かけたら、値を変更しようとしないでください。コンパイラが許しません。

5. 実践: 定数の宣言と利用

例: 定数を持つクラス

public class CircleCalculator 
{
    public static final double PI = 3.1415926535;

    public static double getLength(double radius) 
    {
        return 2 * PI * radius;
    }

    public static double getArea(double radius) 
    {
        return PI * radius * radius;
    }
}

使用例:

public class Main 
{
    public static void main(String[] args) 
    {
        double r = 5.0;
        System.out.println("円周の長さ: " + CircleCalculator.getLength(r));
        System.out.println("円の面積: " + CircleCalculator.getArea(r));
    }
}

実行結果:

円周の長さ: 31.415926535
円の面積: 78.5398163375

定数を変更しようとした例

CircleCalculator.PI = 3.14; // コンパイルエラー: cannot assign a value to final variable PI

6. 補足と注意点

オブジェクト参照に対する定数

オブジェクト参照にも final を付けられますが、これ自体はオブジェクトを不変にしません。あくまで、その変数に別の参照を代入できなくするだけです。

final StringBuilder sb = new StringBuilder("Hello");
sb = new StringBuilder("World"); // エラー: 新しいオブジェクトを代入できません
sb.append(", Java!");            // 許可される — オブジェクトの状態が変わるだけ
System.out.println(sb);          // Hello, Java!

結論: final が守るのは参照であって、オブジェクト自体ではありません。本当に不変にしたい場合は、不変クラス(例: StringList.of() など)を使いましょう。

マジックナンバーの代わりに定数を使う

悪い例:

double area = 3.1415 * r * r; // 3.1415 とは何?なぜこの数?

良い例:

double area = PI * r * r; // 円周率を使っているとすぐ分かる

7. 定数と var を扱う際のよくあるミス

エラー1: final 変数の値を変更しようとする。 変数が final で宣言されている場合、再代入はコンパイルエラーになります。

エラー2: var で定数を宣言しようとする。 定数には常に明示的な型と final または static final を使います。var はローカル変数専用です。

エラー3: 定数の命名が不適切。 定数名は UPPER_SNAKE_CASE(大文字+アンダースコア)で記述します。final int maxUsers = 100; のような記法は可読性を下げます。

エラー4: スコープを忘れる。 メソッド内で宣言した定数はそのメソッド内でしか見えません。クラス全体で使う場合は、static final としてクラスレベルに宣言します。

エラー5: final でオブジェクトが不変になると思い込む。 final が固定するのは参照であり、オブジェクトの状態ではありません — この 2 つは別物です。

1
タスク
JAVA 25 SELF, レベル 10, レッスン 2
ロック未解除
クイックな挨拶の宣言 👋
クイックな挨拶の宣言 👋
1
タスク
JAVA 25 SELF, レベル 10, レッスン 2
ロック未解除
変わらない週の日数 📅
変わらない週の日数 📅
1
タスク
JAVA 25 SELF, レベル 10, レッスン 2
ロック未解除
世界のための数学定数 🌍
世界のための数学定数 🌍
1
タスク
JAVA 25 SELF, レベル 10, レッスン 2
ロック未解除
最大プレイヤー数の設定 🚫
最大プレイヤー数の設定 🚫
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION