リテラルの罠
リテラルの罠
このレッスンでできるようになること。アンダースコア区切り、2進・8進・16進のリテラル、そして char と int の関係を見分けられるようになります。
まず予測してください
次のコードは何を表示するでしょうか。そもそもコンパイルが通るかどうかから考えてください。
int a = 0b1010;
int b = 017;
int c = 0x1F;
int d = 1_000_000;
char e = 65;
System.out.println(a + " " + b + " " + c + " " + d + " " + e);答えと理由
表示されるのは 10 15 31 1000000 A です。順に見ていきます。
0b1010は2進数です。1010 は 8 + 2 なので 10 になります。0bは Java 7 から使えます017は8進数です。ここが最大の罠で、先頭の 0 だけで8進になります。17 でも 0x17 でもなく、1×8 + 7 で 15 です。日付や時刻をint month = 08;のように書くと、8 は8進の数字として存在しないのでコンパイルエラーになります0x1Fは16進数です。1×16 + 15 で 31 になります。0X1fのように大文字小文字を混ぜても同じ値です- アンダースコアは桁区切りで、値には一切影響しません。
1_000_000はただの 1000000 です char e = 65;は 'A' になります。 char は数値型の一種で、int の定数が char の範囲に収まっていれば代入できます
アンダースコアを置けない場所
アンダースコアは「数字と数字のあいだ」にしか置けません。次はすべてコンパイルエラーです。
int x1 = _1000; // 先頭には置けない。しかもこれは変数名として読まれる
int x2 = 1000_; // 末尾には置けない
double x3 = 1_.5; // 小数点の隣には置けない
double x4 = 1._5; // 小数点の隣には置けない
int x5 = 0_x1F; // 進数の接頭辞の途中には置けない
long x6 = 100_L; // 接尾辞の隣には置けない逆に int ok = 0b1010_1010; や long ok2 = 1_000_000_000_000L; は問題なく通ります。アンダースコアが連続していても通ります。 1__000 は合法です。ここを「連続は不可」と読ませる選択肢がよく出ます。
L 接尾辞
int の範囲を超えるリテラルには L が要ります。long big = 10000000000; は、まず int のリテラルとして読まれてから範囲外と判定されるのでコンパイルエラーです。10000000000L と書けば通ります。小文字の l も文法上は使えますが、数字の 1 と見分けがつかないため試験でもわざと紛らわしく出されます。
char と int の行き来
char を計算に使うと int に昇格 します。だから char c = 'A'; System.out.println(c + 1); は B ではなく 66 を表示します。文字として出したければ (char)(c + 1) とキャストし直す必要があります。一方 System.out.println("" + c + 1); は文字列の連結になるので A1 です。この3つの違いが、そのまま選択肢として並びます。
まとめ
先頭の 0 は8進、アンダースコアは数字と数字のあいだだけ、char は計算すると int になります。この3つを押さえておけば、リテラルの出題は取り切れます。
要件
- 0b1010 / 017 / 0x1F / 1_000_000 の4つのリテラルをそのままの表記で使うこと
- char 型の変数に 65 を代入すること
- char そのものと、char に 1 を足した結果の両方を文字列に含めること
- 6つの項目を半角スペース1つでつないだ文字列を返すこと
入出力例
literals() → "10 15 31 1000000 A 66"
literals() → "10 15 31 1000000 A 66"