Java道|Javaの文字コードのしくみ

文字は見た目だけでなく、数字でも管理されている。
文字コードのしくみを知ると、Javaの文字の世界がもっと深く見えてくる。

これまでに、Javaでは文字や文字列をリテラルとして書けること、そしてエスケープシーケンスを使うと改行や特別な記号を表せることを学んできました。

画面に A や あ や 春 と表示されると、私たちはそれをそのまま文字として見ます。
けれども、コンピュータの内部では、文字は見た目の形そのものとして管理されているわけではありません。

コンピュータは、文字を 数値 と対応させて管理しています。

たとえば、人間にとって A と a は見た目が違う文字です。
コンピュータの内部でも、A にはA用の数値、a にはa用の数値が割り当てられています。
日本語の あ や 春 のような文字にも、それぞれ対応する数値があります。

このような 文字と数値の対応 を表すしくみが、文字コードです。Javaでは文字を扱うときに Unicode という文字コードのしくみが使われており、アルファベットだけでなく、日本語や記号など、さまざまな文字を扱えるようになっています。さらに、エスケープシーケンスを使うと、文字コードを直接指定して文字を表示することもできます。

鬼滅の刃の世界観にたとえるなら、文字コードは 文字に割り当てられた隊士番号 のようなものです。

Javaの考え方鬼滅風のたとえ
文字隊士や技の名前
文字コード文字に割り当てられた隊士番号
Unicode世界中の文字を管理する大きな名簿
\1028進数で指定した文字の番号
\u004216進数で指定した文字の番号
画面表示番号から文字の姿を呼び出すこと

文字コードを理解すると、Javaで扱っている文字が、ただ画面に見えているだけの存在ではないことが分かります。
文字の裏側には数値があり、その数値によってコンピュータは文字を区別しているのです。

文字はコンピュータの中で数値として扱われている

私たちは、画面に表示された文字をそのまま文字として見ています。

たとえば、次のような文字です。

文字人間の見方
Aアルファベットの大文字A
aアルファベットの小文字a
ひらがなのあ
漢字の春

人間は形を見れば、その文字が何かを判断できます。

しかし、コンピュータは文字の形そのものを人間のように理解しているわけではありません。
内部では、それぞれの文字に対応する数値を使って管理しています。

文字コンピュータ内部での考え方
AAに対応する数値として扱う
aaに対応する数値として扱う
あに対応する数値として扱う
春に対応する数値として扱う

つまり、コンピュータにとって文字は、見た目の形だけではなく、決められた番号と結びついたものです。

鬼滅風にたとえるなら、隊士を名前だけでなく、隊士番号でも管理するようなものです。
A隊士、a隊士、あ隊士、春隊士には、それぞれ別の番号が割り当てられています。

この番号があるから、コンピュータは文字を区別できます。

文字コードとは何か

文字コードとは、文字に対応づけられた数値のことです。

もう少しやさしく言うと、この文字はこの番号で表す という対応表のようなものです。

たとえば、ある文字コードのルールの中で、A にはある数値、a には別の数値、あ にはさらに別の数値が割り当てられているとします。

文字対応する数値のイメージコンピュータの見方
AA用の番号数値として管理する
aa用の番号数値として管理する
あ用の番号数値として管理する
春用の番号数値として管理する

このように、文字と数値を対応させるしくみが文字コードです。

Javaで文字を表示するとき、私たちは文字そのものを書いているように感じます。
しかし、内部ではその文字に対応するコードが使われています。

鬼滅風に言えば、文字コードは「隊士名簿」です。
名簿には、文字という名前と、それに対応する番号が書かれています。

名簿の項目Javaでの対応
隊士の名前文字
隊士番号文字コード
名簿全体文字コード体系

この名簿があるから、コンピュータは画面に正しい文字を表示できます。

JavaではUnicodeが使われている

Javaでは、文字コードとして Unicode が使われています。

Unicodeは、世界中のさまざまな文字を統一的に扱うための文字コード体系です。

英字や数字だけでなく、日本語、記号、さまざまな国の文字を表せるように考えられています。

Javaで次のような文字を扱えるのも、Unicodeのしくみがあるからです。

'A'
'あ'
'春'
"こんにちは"

これらは、見た目には普通の文字に見えます。
しかし、Javaの内部ではUnicodeに基づく数値として扱われています。

Unicodeの特徴を整理すると、次のようになります。

特徴内容
多くの文字を扱える英字、数字、日本語、記号などを幅広く表せる
世界中の文字に対応しやすい多言語のプログラムでも扱いやすい
Javaと相性がよいJavaの文字の基本的な扱いに使われている
文字と数値を対応させる文字を内部で管理しやすくする

鬼滅風にたとえるなら、Unicodeは世界中の隊士や技名をまとめて管理する巨大な名簿です。

日本の文字だけでなく、いろいろな国の文字や記号も同じ名簿で管理できるため、Javaは幅広い文字を扱いやすくなっています。

エスケープシーケンスで文字コードを指定できる

Javaでは、文字そのものを直接書くだけでなく、文字コードを指定して文字を表すこともできます。

代表的な書き方は、次の2つです。

書き方意味
\ooo8進数で表した文字コードの文字
\uhhhh16進数で表した文字コードの文字

ここで、ooo や hhhh には数字や記号が入ります。

たとえば、次のような書き方があります。

書き方意味
\1028進数で文字コードを指定する
\u004216進数で文字コードを指定する

このように書くと、Javaはその文字コードに対応する文字を探して表示します。

たとえば、\102 と \u0042 は、どちらも文字 B を表す例として使えます。

鬼滅風に言えば、文字そのものを呼ぶ代わりに、隊士番号を呼んで、その番号に対応する隊士を登場させるようなものです。

呼び方鬼滅風のイメージ
B と直接書く隊士名を直接呼ぶ
\102 と書く8進数の隊士番号で呼ぶ
\u0042 と書く16進数の隊士番号で呼ぶ

呼び方は違っても、対応する番号が同じ文字を指していれば、表示される文字は同じになります。

文字コードを使ってみよう

文字コードを指定して文字を表示する例を、Sample5.javaで確認します。

ファイル名:Sample5.java

// 文字コードを使って文字を表示するプログラム
class Sample5
{
    public static void main(String[] args)
    {
        System.out.println("8進数102の文字は \102 です。");
        System.out.println("16進数0042の文字は \u0042 です。");
    }
}

このプログラムを実行すると、画面には次のように表示されます。

8進数102の文字は B です。
16進数0042の文字は B です。

コードの中では、\102 や \u0042 と書いています。
しかし、画面にはそのまま \102 や \u0042 と表示されるのではありません。

Javaがそれらを文字コードの指定として読み取り、対応する文字 B に変換して表示します。

コードに書いたもの意味画面に表示される文字
\1028進数で指定した文字コードB
\u004216進数で指定した文字コードB

このように、文字コードを使うと、文字そのものを書かなくても、対応する文字を表示できます。

6行目では8進数の文字コードを使っている

Sample5.javaの6行目の表示文を見てみましょう。

System.out.println("8進数102の文字は \102 です。");

この中にある \102 は、8進数で表した文字コードです。

Javaは \102 を見つけると、これは8進数で指定された文字コードだと判断します。
そして、そのコードに対応する文字を表示します。

この例では、\102 に対応する文字が B なので、画面には次のように表示されます。

8進数102の文字は B です。

コード上では \102 と書かれていますが、実行結果では B になります。

コード上の表記Javaでの意味実行結果での表示
\1028進数の文字コード指定B

鬼滅風にたとえるなら、\102 は8進数で書かれた隊士番号です。
Javaはその番号を名簿で調べて、対応する文字 B を呼び出します。

7行目では16進数の文字コードを使っている

次に、Sample5.javaの7行目の表示文を見てみます。

System.out.println("16進数0042の文字は \u0042 です。");

ここで使われている \u0042 は、16進数で表した文字コードです。

Javaは \u0042 をUnicodeの文字コード指定として読み取り、それに対応する文字を表示します。

この例では、\u0042 に対応する文字も B です。

実行結果は次のようになります。

16進数0042の文字は B です。
コード上の表記Javaでの意味実行結果での表示
\u004216進数の文字コード指定B

つまり、8進数で書いても、16進数で書いても、最終的に同じ文字コードを表していれば同じ文字が表示されます。

鬼滅風に言えば、8進数の隊士番号札と16進数の隊士番号札で書き方は違っても、同じ隊士番号を指していれば、同じ隊士が現れるということです。

文字コードを指定すると文字が表示される流れ

文字コードを指定したとき、Javaの中では次のような流れで文字が表示されます。

たとえば、\u0042 を考えてみます。

順番Javaの動き
1コードの中に \u0042 が書かれている
2Javaが16進数の文字コード指定だと判断する
3Unicodeの対応表から該当する文字を探す
4対応する文字 B を画面に表示する

この流れを知ると、文字コードがただの数字ではないことが分かります。

文字コードは、文字を表示するための番号です。
Javaはその番号を手がかりにして、対応する文字を呼び出します。

鬼滅風にたとえるなら、Javaは巨大なUnicode名簿を持っている案内役です。
\u0042 という番号札を見せると、名簿から該当する文字 B を探して、画面に出してくれます。

図:文字コードと文字の対応

↓クリックすると拡大表示されます。

この図は、\102 や \u0042 のような文字コード指定が、Javaによって文字 B として表示される流れを表しています。

この図から分かることは、コードに書いた \102 や \u0042 が、そのまま文字列として表示されるわけではないということです。
Javaはそれらを文字コードとして読み取り、対応する文字を探して画面に表示します。

また、8進数と16進数で書き方が違っても、対応する文字が同じなら、同じ B が表示されることも分かります。

8進数と16進数は数値の表し方の違い

Sample5.javaでは、8進数と16進数が出てきました。

System.out.println("8進数102の文字は \102 です。");
System.out.println("16進数0042の文字は \u0042 です。");

ここで出てくる8進数と16進数は、数値の表し方の違いです。

普段、私たちがよく使っているのは10進数です。
10進数は、0から9までの数字を使って数を表します。

一方、8進数は0から7までを使います。
16進数は0から9に加えて、AからFも使います。

表し方使う記号
10進数0〜9
8進数0〜7
16進数0〜9、A〜F

今の段階では、細かい変換計算まで覚えなくても大丈夫です。

まずは、次のように押さえましょう。

書き方意味
\ooo8進数で文字コードを表す
\uhhhh16進数で文字コードを表す

鬼滅風にたとえるなら、同じ隊士番号でも、番号札の書き方が複数あるようなものです。
10進数札、8進数札、16進数札のように、表し方が違っても、最終的に指すものが同じなら同じ文字につながります。

文字そのものを書く方法と文字コードで書く方法

Javaでは、文字を表す方法はいくつかあります。

たとえば、B を表示したいとき、直接文字を書くこともできます。

System.out.println("文字は B です。");

一方、文字コードを使って書くこともできます。

System.out.println("文字は \u0042 です。");

どちらも実行結果は同じように B を表示します。

書き方読みやすさ特徴
文字は B です。高い何の文字かすぐ分かる
文字は \u0042 です。やや低い文字コードとの対応を意識できる

普段のプログラムでは、直接文字を書くことが多いです。

しかし、文字コードのしくみを学ぶときには、\u0042 のように文字コードで書く方法を知っておくことが役立ちます。

鬼滅風に言えば、隊士を名前で呼ぶこともできるし、隊士番号で呼ぶこともできる、ということです。
名前で呼ぶ方が分かりやすいですが、番号で呼ぶと、裏側の管理のしくみが見えてきます。

文字コードを知ると文字の扱い方が深く見えてくる

文字コードの考え方を知ると、Javaの文字の見え方が変わります。

画面に表示された文字は、ただ形として存在しているだけではありません。
その裏側では、文字と数値の対応が使われています。

文字コードを知ると、次のような疑問がつながって見えてきます。

疑問文字コードを知ると分かること
なぜ文字にコードがあるのかコンピュータが文字を数値で管理するため
なぜエスケープシーケンスで文字を表せるのか文字コードを指定して文字を呼び出せるため
なぜUnicodeが必要なのか多くの文字を統一的に扱うため
なぜ日本語も扱えるのかUnicodeに日本語の文字も含まれているため

つまり、文字コードを知ることは、文字の見た目の奥にある コンピュータの考え方 を知ることでもあります。

鬼滅風にたとえるなら、技の見た目だけでなく、技を管理する名簿や番号札まで理解する修行です。
表に見える文字の裏側には、文字コードという仕組みがあります。

図:Javaの文字コードのしくみ

↓クリックすると拡大表示されます。

この図は、私たちが見ている文字と、Java内部で扱われる文字コードの関係を表しています。

この図から分かることは、文字は見た目だけで管理されているのではなく、内部では数値と対応しているということです。

また、JavaではUnicodeによって多くの文字を扱えること、そして \u0042 や \102 のような文字コード指定から、対応する文字 B を表示できることも分かります。

Sample5.javaで確認できる大切なこと

もう一度、今回のサンプルを確認します。

ファイル名:Sample5.java

// 文字コードを使って文字を表示するプログラム
class Sample5
{
    public static void main(String[] args)
    {
        System.out.println("8進数102の文字は \102 です。");
        System.out.println("16進数0042の文字は \u0042 です。");
    }
}

このプログラムから確認できることを整理します。

確認できること内容
文字は内部で数値として扱われるコンピュータは文字コードで文字を管理する
JavaではUnicodeが使われる多くの文字を統一的に扱える
\ooo8進数で文字コードを指定できる
\uhhhh16進数で文字コードを指定できる
文字コードから文字を表示できる指定したコードに対応する文字が表示される
\102 と \u0042 はどちらも B を表示する書き方が違っても同じ文字を表せる

文字コードは、最初は少し抽象的に感じるかもしれません。

でも、エスケープシーケンスと結びつけて見ると、文字と数値がどのように対応しているのかが見えやすくなります。

Javaで文字を学ぶときは、画面に見えている文字だけでなく、その裏側でコンピュータがどのように文字を管理しているのかにも少しずつ目を向けていきましょう。