0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Javaのchar型と、Goのrune型は何が違う?

Posted at

はじめに

Goには「1つの文字」を表現するためのrune型があります。筆者は普段Javaを書いているため「char型みたいなものか」と思っていましたが、少し扱いが異なる点について、(忘れるうちに)まとめてみました。

対象読者

  • Javaでの開発経験があり、これからGo言語を学び始めようとしている方
  • Javaのchar型と、Goのrune型との違いを理解したい方
  • Javaのchar型やサロゲートペアの仕組みについて、改めて復習したい方

Javaのchar型はUTF-16コード単位

Javaの文字リテラルが表せるのはUTF-16の1コード単位(code unit)に限られます。
つまり、charで表せるのは全UnicodeU+0000U+10FFFFのうち、U+0000U+FFFF のみとなります(U+10000U+10FFFFは扱えない)。

これは、Javaが設計された当初のUnicodeが16ビットであったためですが、時が経つにつれて扱える文字数が増加したという歴史的背景があります(詳細は割愛します)

そのため、charに「😀」(U+1F600)のような絵文字を指定するとコンパイルエラーになってしまいます。

public class Main {
    public static void main(String[] args) {
        char c = '😀';  // コンパイルエラー
        System.out.println(c);
    }
}

Javaでこれらの文字を扱う方法としては、主に以下2つの方法があります。

  • サロゲートペア(2つのchar)として表す
  • Unicodeコードポイント(整数)として扱う
public class Main {
    public static void main(String[] args) {
        // サロゲートペアを使って表す方法
        String surrogate = "\uD83D\uDE00";  // または、String surrogate = "😀";
        System.out.println(surrogate);      // 😀

        // Unicodeコードポイント(整数)で表す方法
        int codePoint = 0x1F600;  // または、int codePoint = 128512;
        System.out.println(new String(Character.toChars(codePoint)));  // 😀
    }
}

Goのrune型はUnicodeコードポイントそのもの

一方、Goのrune型はint32型の別名(つまりは整数型)で、Unicodeコードポイントそのものを表します。
つまり、Javaで2つのcharが必要だった絵文字も、Goでは1つのruneで表現できます。

package main

import "fmt"

func main() {
	var r rune = '😀'     // runeリテラル
	fmt.Println(r)        // 128512
	fmt.Printf("%c\n", r) // 😀
}

また、UnicodeコードポイントでU+10000以上のruneを表現する場合は、主に以下2つの方法があります。

  • Unicodeエスケープ(\U)のruneリテラルで表す方法
  • 整数リテラルで表す方法
package main

import "fmt"

func main() {
	// Unicodeエスケープ(\U)のruneリテラルで表す方法
	var r2 rune = '\U0001F600' // 32ビットUnicodeコードポイント(16進数で指定したruneリテラル)
	fmt.Println(r2)            // 128512
	fmt.Printf("%c\n", r2)     // 😀

	// 整数リテラルで表す方法
	var r3 rune = 0x1F600   // または、var r3 rune = 128512
	fmt.Println(r3)        // 128512
	fmt.Printf("%c\n", r3) // 😀
}

まとめ

最後に、Javaのcharと、Goのruneの共通点や相違点についてまとめます。
どちらもUnicodeコードポイントを整数として扱えますが、Goのruneは1つで任意のUnicodeコードポイントを表現できるのに対し、JavaのcharはU+10000以上の文字については、2つのcharで表現する必要があるため、注意しましょう。
charやruneは極力使わないでStringを使いましょう。

項目 Java (char) Go (rune)
意味するもの UTF-16コード単位 Unicodeコードポイント
表現できる範囲 U+0000U+FFFF U+0000U+10FFFF(Unicode全範囲)
絵文字 (例: '😀') サロゲートペアにすれば扱える 扱える
Unicodeコードポイント(整数型) int型にすれば扱える 扱える

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?