🟢 はじめに
今回は、私がJavaを学習中に「えっ、なんでここでエラーになるの!?」と疑問に思った「数値の計算時に起きる型のトラップ」について解説します。
例えば、小さな数値を入れる short 型同士を足し算すると、どうなると思いますか?
実はこれ、そのままではコンパイルエラーになってしまいます。
今回は、このちょっと不思議なJavaの仕様を、RPGのジョブ(職業)に例えて分かりやすく紐解いていきます!
1. パーティを組むと勝手にレベルアップ!?(型の昇格)
まずは、こちらのコードを見てください。
村人Aと村人BのHPを合わせて、合計HPを出そうとしています。
public class Main {
public static void main(String[] args) {
// short型(村人)の変数を用意
short villagerA_HP = 10;
short villagerB_HP = 20;
// 合計HPをshort型の箱に入れようとすると…
// short totalHP = villagerA_HP + villagerB_HP; // ⚠️ここでコンパイルエラー!
}
}
両方とも short 型のデータなので、足し算した結果も short 型の箱(変数)にスッポリ入りそうですよね。
でも、Javaではここでエラーが起きます。
なぜかというと、Javaの世界には「算術演算子(+ や - など)を使って計算をする時、
int より小さなジョブは、自動的に標準装備の int(勇者)にパワーアップしてから戦う」という絶対のルールがあるからです。
これを専門用語で「型の昇格(プロモーション)」と呼びます。
つまり、villagerA_HP + villagerB_HP が実行された瞬間、その計算結果は short(村人)ではなく、より大きなデータが入る int(勇者) になります!
大きくなってしまった int(勇者)の結果を、小さな short(村人)の箱に無理やり戻そうとするため、「箱に入りきらないよ!」とコンパイラが怒ってしまうわけですね。
2. エラーを回避する2つの方法
このエラーを防ぐには、主に2つの方法があります。
① 素直に int(勇者)の箱で受け取る
一番安全で自然な方法です。
結果が int になるなら、最初から int の箱を用意しておきましょう。
// int型(勇者サイズの箱)なら問題なく受け取れる!
int totalHP_Int = villagerA_HP + villagerB_HP;
② 強制的に short(村人)に戻す(キャスト)
どうしても short の箱に入れたい場合は、「自己責任で小さくします!」という宣言をします。
これをキャストと呼びます。
// (short)をつけて、強制的に村人サイズに圧縮する!
short totalHP_Short = (short)(villagerA_HP + villagerB_HP);
3. 最大の謎:なぜ ++ ならエラーにならないの?
ここまでの話を聞くと、次のような疑問が湧いてきませんか?
「+ を使うと int になっちゃうなら、++(インクリメント)を使ってもエラーになるんじゃないの?」
実は、ここがJavaの面白いところです。
以下のコードを見てください。
short level = 1;
level++; // ⚠️エラーにならない!!
System.out.println(level); // 結果は2
+ を使った計算ではエラーになったのに、level++ はエラーになりません。
理由は、++(インクリメント)や += などの「複合代入演算子」には、内部的に「元のジョブ(型)を維持したまま計算し、自動でキャスト(型変換)まで行ってくれる特殊スキル」が備わっているからです。
level++ は、内部的にはこのように処理されています。
level = (short)(level + 1);
わざわざ自分で (short) と書かなくても、裏側でJavaが「おっと、この箱は short だったね。じゃあ計算結果も short にして戻しておくよ」と気を利かせてくれているのです。
✍️ まとめ
-
shortやbyteなどの小さな型は、+などで計算すると自動的にint(勇者)に昇格する。 -
昇格した結果を元の小さな箱に入れるには、
intで受け取るか、(short)のように明示的なキャストが必要。 -
++などの複合代入演算子には、元の型を維持する特殊スキル(自動キャスト機能)がついているためエラーにならない!
この「型の振る舞い」を理解しておくと、思わぬコンパイルエラーを防ぐことができると思います。
Java学習中の方の参考になれば幸いです🙌