char の演算と文字コード
charは演算するとintに昇格します。'0'を引く定番テクニックの仕組みも解説します。
なぜエラーが出ないのか
出力: 98
(エラーなし)- javacは何も報告しません。文法として正しいためです
出力: 98- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 public class Main { 2 public static void main(String[] args) { 3 char c = 'a'; 4 System.out.println(c + 1 ); ^ 5 } 6 }
charは演算するとintに昇格します。文字として出したければcharへ戻すキャストが要ります。
直し方: c + 1 を (char) (c + 1) にします。
パターン2
1 public class Main { 2 public static void main(String[] args) { 3 String s = "123"; 4 int d = s.charAt(0) ; ^ 5 System.out.println(d); 6 } 7 }
文字'1'の数値は49です。'0'を引くと文字コードの差が取れて数値の1になります。
直し方: (空) を - '0' にします。
パターン3
1 public class Main { 2 public static void main(String[] args) { 3 String s = "java"; 4 for (int i = 0; i < s.length(); i++) { 5 System.out.print(s.get (i)); ^ 6 } 7 } 8 }
1文字取り出すのはcharAt(i)です。Stringにはget(int)というメソッドはありません(Listのgetと混同しやすい箇所です)。
直し方: get を charAt にします。
パターン4
1 public class Main { 2 public static void main(String[] args) { 3 char c = '7'; 4 int n = c ; ^ 5 System.out.println(n * 2); 6 } 7 }
charをそのままintにすると文字コード(55)になります。数字としての値を得るにはCharacter.getNumericValueを使います。
直し方: c を Character.getNumericValue(c) にします。
パターン5
1 public class Main { 2 public static void main(String[] args) { 3 char c = 'a'; 4 char upper = c ; ^ 5 System.out.println(upper); 6 } 7 }
英字の大文字と小文字は文字コードが32違います。演算結果はintになるのでcharへ戻すキャストが要ります。
直し方: c を (char) (c - 32) にします。
よくある誤解
charは数値型です。'a' < 'b' が成り立つのは、文字コードを比較しているからです。
実務での勘所
char c = 'a' + 1;は一見intになるはずなのにコンパイルが通ります。これは'a' + 1が定数式として評価され、値がchar型の範囲に収まると分かっている場合に限りjavacが暗黙に絞り込み変換(narrowing)を許可する特別ルールがあるためです。同じ計算でもchar c = someChar + 1;のようにsomeCharが変数(定数式ではない)だと、この特例は働かずコンパイルエラーになります。「定数式かどうか」で挙動が変わる、地味だが把握しておくと役立つルールです。