Java プリミティブ型

Javaは、ソフトウェア開発で広く使われているプログラミング言語です。Javaにおける重要な概念の1つに、言語の基本的な構成要素を表すプリミティブデータ型という考え方があります。この記事では、Javaのプリミティブデータ型とその使用方法について詳しく見ていきます。

コンピュータプログラミングでは、プリミティブデータ型はプログラムで表現できる最も基本的なデータ型であり、通常プログラミング言語自体に組み込まれています。プリミティブデータ型は通常、整数、浮動小数点数、文字などの単純な値を表現するために使用されます。

Javaには、boolean, char, byte, short, int, long, float, doubleの8つのプリミティブデータ型があります。これらのデータ型はそれぞれ、Java言語において特定の種類の値を表現するために使用されます。

プリミティブ型は、大きく分類すると、整数型、浮動小数点型、文字型、ブーリアン型があります。それでは、これらのデータ型を順番に詳しく見ていきましょう。

Java 整数型

Javaでは、提供されている整数のデータ型によって、取り扱う整数の範囲が異なります。

整数型には、

  • byte型(8ビット): -128 ~ 127
  • short型(16ビット): -32,768 ~ 32,767
  • int型(32ビット): -2147,483,648 ~ 2,147,483,647
  • long型(64ビット): -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807

が存在します。

Java byte型

Javaでは、byte型は8ビットの符号付き整数データ型です。小さな整数を表現するために使用され、範囲は-128から127です。byte型は、ファイルの読み書きのようなバイナリデータを扱うときによく使用されます。

byte型の主な特徴の1つは、符号付きデータ型であることで、正負両方の値を表現することができます。これに対し、char型は符号なしデータ型であり、非負の値しか表すことができません。

以下は、Javaにおけるbyte型の使用例です。

byte b = 100;
System.out.println(b);

Java short型

Javaでは、short型は16ビットの符号付き整数データ型です。byte型よりも大きな整数を表現するために使用され、範囲は-32768から32767までです。byte型と同様に、short型も符号付きデータ型で、正負両方の値を表現できます。

short s = 10000;
System.out.println(s);

Java int型

Javaでは、int型は32ビットの符号付き整数データ型です。short型よりも大きな整数を表現するために使用され、その範囲は-2147483648から2147483647までです。byte型やshort型と同様に、int型は符号付きデータ型で、正と負の両方の値を表現できます。

以下は、Javaでのintデータ型の使用例です。

int i = 1000000000;
System.out.println(i);

Java long型

Javaでは、long型は64ビットの符号付き整数データ型です。非常に大きな整数を表現するために使用され、範囲は-9223372036854775808から9223372036854775807までです。他の整数データ型と同様に、long型は符号付きデータ型であり、正負両方の値を表すことができます。

Javaで最大の整数データ型であり、一般に非常に大きな数値や高い精度が必要な値に使用されます。以下は、Javaでのlongデータ型の使用例です。

long l = 1000000000000L;
System.out.println(l);

この例では、値1000000000000の後に文字"L"が付いており、long値であることを示していることに注意してください。これは整数接尾語と呼ばれ、Javaコンパイラに値をlong型として扱うように指示するために使用されます。

整数リテラルの場合、特に指定しない場合はint型として扱われます。そのため、リテラルがlong型の範囲の数値であってもint型の最大値を超える値を記述してしまうとコンパイル時にエラーとなります。このような場合、上記の例のようにサフィックスを付けて型を指定します。

// Error
long x = 2200000000;

Java 数値の区切り

Javaでは、数値リテラルの桁区切りにアンダースコア文字(_)を使うことで、大きな数値を読みやすくすることができます。例えば、1000000000を1_000_000_000と書くと、各桁の位取りが見やすくなります。

int i = 1_000_000_000;
System.out.println(i);

アンダースコア文字は視覚的な補助として使われるだけで、リテラルの値には何の影響も及しません。Javaコンパイラでは通常の空白文字として扱われ、コード実行時には無視されます。アンダースコアを置けるのは数字と数字の間のみで、以下の場所へは配置できません。

  • 数値の先頭または末尾
  • 浮動小数点リテラルの小数点の隣
  • FまたはL接尾辞の前
  • 文字列の数字の間

Java オーバーフローとアンダーフロー

データ型の範囲外の値を変数に代入しようとすると、オーバーフローまたはアンダーフローが発生します。オーバーフローは、データ型が表現できる最大値よりも大きな値を代入しようとしたときに起こります。例えば、

int i = 2147483647 + 1;
System.out.println(i); //-2147483648

はコンパイルエラーにはならず、-2147483648 が出力されます。数値は内部でビットとして扱われていて、int型の最大値および最小値は以下になります。

int型の最大値:01111111111111111111111111111111 // 2147483647
int型の最小値:10000000000000000000000000000000 //-2147483648

int型の最大値に1を足すと、桁が溢れてオーバーフローを起こし、符号を表すビットが1になるためint型の最小値になります。

Javaでプリミティブなデータ型を扱う際には、このような潜在的な問題に注意することが重要です。間違ったデータ型を使ったり、データ型の範囲外の値を代入すると、予期せぬ結果を招き、コードにエラーを引き起こす可能性さえあります。このような問題を避けるために、扱うべき値を慎重に検討し、適切なデータ型を選択することが望まれます。

class Main{
    public static void main(String[] args){
        int maxIntValue = 2147483647;
        System.out.println(maxIntValue + 1);
    }
}

Javaには、小数点以下の値を持つ実数を表現するためのプリミティブデータ型として、float型とdouble型の2つがあります。これらのデータ型は、浮動小数点表現として知られる形式で値を格納するため、浮動小数点型として知られています。

浮動小数点型には、

  • float型:
    • 32ビット単精度浮動小数点数
    • 符号部1ビット、指数部8ビット、仮数部23ビット
    • 正の値は1.4 × 10-45から3.4 × 1038
    • 負の値は-3.4 × 1038から-1.4 × 10-45
  • double型:
    • 64ビット倍精度浮動小数点数
    • 符号部1ビット、指数部11ビット、仮数部52ビット
    • 正の値は4.9 × 10-324から 1.8 × 10308
    • 負の値は-1.8 × 10308から -4.9 × 10-324

が存在します。

float型やdouble型の浮動小数点型は、正確な近似値を素早く表すためのデータ型です。よって、全ての数値を正確に表現することはできません。ただ、double型ではfloat型に比べ、指数部のビットが増えたことにより、より大きな値を取り扱うことができ、仮数部のビットが増えたことにより、より細かい値を取り扱うことができます。

Java float型

floatデータ型は、32ビット単精度浮動小数点データ型です。doubleデータ型よりも範囲が狭く、精度が低い10進数値を表現するために使用されます。

float f = 3.14f;
System.out.println(f);

この例では値3.14の後には、float値であることを示す文字"f"が付いていることに注意してください。これは浮動小数点接尾語と呼ばれ、Javaコンパイラに値をfloatデータ型として扱うように指示するために使用されます。

Java double型

doubleデータ型は、倍精度の64ビット浮動小数点データ型です。floatデータ型よりも範囲が広く、精度の高い値を表現するために使用されます。

double d = 3.14;
System.out.println(d);

この例では、値3.14の後にdouble値であることを示す特別な文字がないことに注意してください。接尾語で型を指定しない場合はdouble型とみなされます。

一般的には、float型を使用する特別な理由がない限り、double型を使用することをお勧めします。これは、double型は範囲が広く、精度も高いため、ほとんどの用途に適しているからです。

class Main{
    public static void main(String[] args){
        double d1 = 5.0 / 3.0;
        float f1 = 5.0f / 3.0f;
        System.out.println(d1); // 1.6666666666666667
        System.out.println(f1); // 1.6666666
    }
}

Java 型変換

Javaでは、型変換とはあるデータ型から別のデータ型への変換を指します。型変換には、暗黙的なものと明示的なものの2種類があります。

暗黙的な型変換は、目的のデータ型が手元のデータ型の値を表すことができる限り、コンパイラによってあるデータ型から別のデータ型に自動的に変換されます。例えば、int型はdouble型に自動的に変換されます。double型はint型よりも範囲が広いからです。

double d2 = 5;
System.out.println(d2); // 5.0

逆にint型の変数に対してdouble型の値を代入する場合、精度が失われる可能性がある事を意味するエラーが発生します。

int num;
num = 5.0;
System.out.println(num);
// incompatible types: possible lossy conversion from double to intというエラーメッセージが表示されます

明示的な型変換は、キャストとも呼ばれ、プログラマがあるデータ型を別のデータ型に明示的に変換することです。変換はキャスト演算子を使って行います。キャスト演算子は、変換先の型名を括弧で囲み、その後に変換する値を記述します。

int num;
num = (int)5.0;
System.out.println(num);

浮動小数点型の誤差

float型とdouble型は2進数の分数として格納されるため、特定の10進数値を正確に表現することができません。例えば、10進数の0.1はfloatやdoubleでは正確に表現できず、0.1を含む算術演算の結果には丸め誤差が生じます。

以下は、Javaで浮動小数点数を扱う際に発生する可能性のあるエラーの一例です。

class Main{
    public static void main(String[] args){
        double a = 0.1;
        double b = 0.2;
        double c = a + b;

        System.out.println(c); // 0.30000000000000004
    }
}

浮動小数点数を扱う場合、特に金融や科学計算を行う場合には、このような丸め誤差に注意することが重要です。高い精度が要求される場合には、BigDecimalクラスのような別の表現が必要になる場合もあります。別の方法として、小数点の位置を覚えておいてint型やlong型に置き換えて演算を行う方法もあります。

小数の値に10の累乗を掛けて小数点を右にずらし、整数型を使った算術演算を行い、その結果を同じ10の累乗で割って小数点を元の位置に戻せば比較的安全に計算できます。例えば、小数点以下2桁の精度で2つの値を足すには、次のようにします。

double a = 1.23;
double b = 4.56;

int a_int = (int)Math.round(a * 100);
int b_int = (int)Math.round(b * 100);

int c_int = a_int + b_int;
double c = (double) c_int / 100;
System.out.println(c); // 5.79

Java 浮動小数点型の特殊な値について

Javaの浮動小数点データ型には、正の無限大、負の無限大、および無効な値に対する特別な値があります。これらの特殊な値は、通常の浮動小数点値では不可能な特定の数学的演算の結果を表すために使用することができます。

正の無限大の値は、Javaでは定数Double.POSITIVE_INFINITYで表され、負の無限大の値は定数Double.NEGATIVE_INFINITYで表されます。これらの定数は、データ型で表現できる最大値を超える演算結果を表現するために使うことができます。

例えば、ある整数型を0で割ると実行時にArithmeticExceptionがスローされます。しかし、浮動小数点数型の場合は、0で割ってもエラーが発生せず、割られる値の符号に応じて、結果は正の無限大か負の無限大になります。

NaN(not-a-number)値は、Javaでは定数Double.NaNで表され、不可能または定義されていない演算の結果を表すために使用されます。例えば、ゼロをゼロで割ろうとすると、結果はNaNになります。

class Main{
    public static void main(String[] args){
        double d1 = Double.POSITIVE_INFINITY;
        double d2 = Double.NEGATIVE_INFINITY;
        double d3 = Double.NaN;

        System.out.println(d1);
        System.out.println(d2);
        System.out.println(d3);

        System.out.println(3.14/0);
        System.out.println(-3.14/0);
        System.out.println(0f/0f);
    }
}

Java 文字型

一つの文字を格納するためのデータ型として、以下が存在します。

  • char型(16ビット): Unicode文字 '\u0000'(0) ~ '\uFFFF' (65535)

実際には文字コードである数値が格納されており、デフォルト値は'\u0000'です。

char型の変数に文字を代入する場合は、'a'のように文字リテラルとして代入したり、文字コードを使って'\u0061'のように代入します。 Javaでは、文字リテラルを表現する際は、シングルクォーテーションが使われます。

char letter = 'A';
System.out.println(letter);

1つの文字に対して1つの文字コードが割り当てられています。以下はすべて同じAを表し、trueを返します。

System.out.println('A' == 0b1000001); // 2進数
System.out.println('A' == 65); // 10進数
System.out.println('A' == 0x41); // 16進数
System.out.println('A' == '\u0041'); // 文字コード

Java 文字型の足し算

Javaでは、charデータ型は実は裏では整数型であり、16ビットの符号なし整数として格納されます。つまり、char型は他の整数型(byte, short, int, long)と同じように算術演算に使用することができます。char型 + char型は数値として扱われることに注意が必要です。

System.out.println('a' + 'b'); // 195

Java ブーリアン型

Javaでは、ブーリアン型は、trueまたはfalseの2つの値のいずれかを保持することができるプリミティブ型です。真/偽の条件やYES/NOの値を表現するためによく使われます。

boolean flag = true;

ブーリアン型は、==や!=のような比較演算子と一緒に使われます。

int x = 10;
int y = 20;

boolean isEqual = (x == y);

if (isEqual) {
    System.out.println("x is equal to y");
} else {
    System.out.println("x is not equal to y");
}

この記事を書いた人

著者の画像

Jeffry Alvarado

Ex-Facebook Engineer 大学ではコンピュータサイエンスを専攻し、在学中に複数のインターンシップを経験。コンピュータサイエンスが学習できるプラットフォームRecursionを創業し、CTOとしてカリキュラム作成、ソフトウェア開発を担当。


ツイート