連載
» 2006年05月24日 10時00分 公開

JavaTips 〜Javaプログラミング編:switch-case構文で型変換エラーが出る

[平野正喜,@IT]

 int型をbyte型に変更すると、変数のメモリ使用量は論理的に半分以下になります。また、char型をbyte型に変更すると、メモリのサイズ減少に加えて負の数(マイナス値)も扱えるようになります。

 switch-case構文を使い、16進コードの値によって振り分けを行う以下のようなコード(画面1)がありますが、上記のような理由で、byte型に変更してみました(画面2)。ところで、byte型にしたのは、変数「ccode」が負の数「-126」になる場合も想定してのことです。

 ところが、実行するとエラーになります。型をcharからbyteに変更しただけなのに、intからbyteには変換できないというエラーがなぜ出てしまうのでしょうか?

画面1 16進コードによる振り分けを行うプログラム 画面1 16進コードによる振り分けを行うプログラム
画面2 変更後のエラーになるプログラム 画面2 変更後のエラーになるプログラム(この例では、エラーメッセージを見やすくするために、「必要なプロジェクトにエラーがあります」というメッセージを無視して実行している)

原因はswitch-case構文の特殊な制限

 Javaでは、整数リテラルは(longであると明示した場合を除き)int型として扱われます。そして、リテラルの代入において、代入先の変数がint型より小さい場合、その型の大きさを超える値はコンパイルでチェックされてエラーになります。

 しかし、if文における基本型同士の比較においては比較相手の型を意識した柔軟な対応が自動的に行われ、エラーにはなりません。

画面3 switch-case構文if文で書き換えたプログラム(正常に動作する) 画面3 switch-case構文if文で書き換えたプログラム(正常に動作する)

 ところが実は、switch-case構文での整数リテラルの扱いは異なります。switch文の対象となるのは基本型のみで、しかもint型だけなのです。こう書くと「char型、byte型、short型も使えるはずでは?」と疑問が出るでしょう。実は、この3つの型からは暗黙的にint型にキャストできます。よって、内部的な解決が可能なため、エラーにならないのです(同じ整数型の仲間であるlong型は、int型に暗黙にキャストすることができないのでcase句には使えません)。

 そして、case句に指定された整数リテラル(case句には初期化済の定数も指定できますが、今回のような場合では、初期化の時点でコンパイルエラーになります)は、内部的に、switch文で指定された変数または式の型に合わせた領域に納まるかどうかチェックされ、納まらない値は本来のint型として扱われます。ですから「byte bcode = 128;」というような不正な代入をした場合と同じ「型の不一致: int から byte には変換できません。」というエラーが表示されるわけです。

 よって、case句においては実行効率が低く、扱いに注意が必要なchar型、byte型、short型は(どうしても必要な場合を除いて)使わない方が望ましいことがわかります。

Profile

RunDog.org

平野正喜


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。