Java データ型(Data type)

Java 言語のデータ型

各変数は、それらが持つことのできる資料型に応じてさまざまな形に分類できる。

基本資料型(Data type)には整数、実数、文字、論理値などの資料型があり、参照資料型には配列、クラス、インターフェースなどがある。基本資料型変数は、それが表そうとする基本資料型の値を持つ一方、参照資料型変数は値への参照、つまりメモリアドレスを持つ。この違いは他のオブジェクトのメソッドを呼び出すときに現れる。

  • 定数(Constant): 常に一定の値を維持するデータである。
  • 変数(Variable): 特定の状況に応じて値が変わるデータである。
  • 資料型(Data Type): 定数や変数に流動的なデータを保存するために指定するデータの形式をいう。資料型は種類によってそれぞれ異なるメモリサイズを持つ。

資料型の分類

Java のデータ型は 8 種類の基本型(primitive type)と参照型(reference type)で構成されている。

分類すると次のようになる。

  • Java Data Type
    • Primitive Type
      • Boolean Type(boolean)
      • Numeric Type
        • Integral Type
          • Integer Type(short, int, long)
          • Floating Point Type(float, double)
        • Character Type(char)
    • Reference Type
      • Class Type
        • String Type
        • Wrapper Class
      • Interface Type
      • Array Type
      • Enum Type

基本資料型: Primitive Type

基本型には次の特徴がある。

  • 基本資料型は必ず使用前に宣言されていなければならない。
  • OS によって資料型の長さは変わらない。
  • オブジェクトではないため null を持つことはできない。

Java 基本資料型のサイズと範囲は次のとおりである。

説明 サイズ(bit) 範囲
char 16 ビット Unicode 文字データ 16 ‘\u0000’ ~ ‘\uFFFF’
boolean 真/偽の値 8 true または false
byte 符号付き 8 ビット整数 8 -128 ~ +127
short 符号付き 16 ビット整数 16 -32,768 ~ +32,767
int 符号付き 32 ビット整数 32 -2,147,483,638~+2,147,483,647
long 符号付き 64 ビット整数 64 -9223372036854775808~+9223372036854775807
float 符号付き 32 ビット浮動小数点 32 -3.402932347e+38~+3.40292347e+38
double 符号付き 64 ビット浮動小数点 64 -179769313486231570e+308~1.79769313486231570e+08
  • 文字型: char
  • 論理型: boolean
  • 整数型: byte, short, int, long
  • 浮動小数点型: float, double

BigInteger

long 型を使う場合、最大値は 9223372036854775807 である。これより本当に大きな数が必要な場合は BigInteger を使う必要がある。
BigInteger は通常の演算子を使えず、.add().subtract().multiply().divide() メソッドが提供され、引数も BigInteger を受け取る。

参照型: Reference Type

参照型は基本型 8 種類を除いたすべてのデータ型で、基本的に java.lang.Object を継承する。
参照型の変数はデータそのものを保存せず、データを保存するメモリのアドレスだけを保存する。つまり、参照型の変数はデータを別の領域に保存し、そのアドレスだけを利用する。

Class Type

クラス型は基本型とは異なり、オブジェクトを参照する形である。

例を通じて見てみよう。

次のオブジェクトは単に str 変数を持つクラスである。

package com.devkuma.basic.datatype.ex1;

class MyObject {
    private String str;

    public MyObject(String str) {
        this.str = str;
    }

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }
}

次のオブジェクトは MyObject を利用して str の値を表示している。

package com.devkuma.basic.datatype.ex1;

public class MyObjectMain {
    public static void main(String[] args) {
        MyObject a = new MyObject("a");
        MyObject b = new MyObject("b");

        // 初期値表示
        System.out.println(a.getStr()); // a
        System.out.println(b.getStr()); // b

        // a に b を代入
        a = b;
        System.out.println(a.getStr()); // b

        // b の str に値 "c" を代入
        b.setStr("c");
        System.out.println(a.getStr()); // c
    }
}

実行結果:

a
b
b
c

最初にオブジェクト b を a に代入し、a を表示すると “b” が表示されることを確認できる。その後、b の str 変数に値 “c” を代入して a を表示すると “c” が表示された。

これは、オブジェクト a と b という変数が持っているのは実際のオブジェクトではなく、オブジェクトのアドレスだからである。a と b は同じオブジェクトのアドレスを持っているため、どちらか一方が変わっても値は同じになる。

String Type

クラス型の中でも String クラスは少し特別である。このクラスは参照型に属するが、基本的な使用方法は基本型のように使う。そして不変(immutable)オブジェクトである。
String クラスには値を変更するように見えるメソッドが存在するが、そのメソッドを通じてデータを変更すると、新しい String クラスオブジェクトを作ることになる。

一般的に基本型の比較は == 演算子を使うが、String オブジェクト同士の比較は .equals() メソッドを使う必要がある。

Wrapper Class

基本型は前述したようにオブジェクトではないため null を入れることはできないが、Wrapper Class を使うと null を入れられる。 ラッパークラスは基本型をクラスで包んだ形のオブジェクトであるため、null を宣言できる。

基本型 ラッパークラス
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Char
boolean Boolean

Interface Type

次のようにインターフェースを作ってみよう。ここで T はジェネリック型で、オプションである。

interface MyInterface<T> {
    void add(T value);
}

インターフェースを作ることは、新しい参照資料型を作ることと同じである。そしてインターフェースも資料型であるため、資料型として自分を実装したオブジェクトのアドレスを持つことができる。ただし、インターフェースに定義されたメソッドだけを使用できる。

Array Type: 配列型

配列型は基本型でも作ることができ、参照型でも作ることができる。

int[] num1 = new int[2];
Integer[] num2 = new Integer[3];

資料型に対して [] を宣言することで配列を指定できる。配列型変数も配列のアドレスを持っているため、クラス型の特徴と同じである。そのため、同じオブジェクトのアドレスを参照すると同じ配列を指す。

そして次のコードのように [][] などの入れ子括弧を使うと、多次元配列として使用できる。

Object[][] obj = new Object[2][3];

Enum Type: 列挙型

enum(列挙型)とは、複数の定数をまとめて扱うためのデータ型である。

enum(列挙型)定義

[modifier] enum name {
  member, ...
}
  modifier: 修飾子(`public`, `strictfp` のみ)
  name: 列挙型の名前
  member: 列挙定数

列挙型の宣言には enum キーワードを使う。enum ブロックの下に名前(列挙定数)をカンマで区切って並べる。定数のように扱うため、名前はアンダースコア(_)形式(すべて大文字、単語の区切りはアンダースコア)にするのが一般的である。

たとえば、次は曜日を表す WeekdayEnum 列挙型を定義する例である。

public enum WeekdayEnum {
    Sunday,
    Monday,
    Tuesday,
    Wednesday,
    Tursday,
    Friday,
    Saturday
}

定義した列挙型には WeekdayEnum.Sunday のように 型名.定数 の形式でアクセスできる。

enum(列挙型)メソッド

列挙型は暗黙的に Enum クラス(java.lang パッケージ)を継承したクラスの一種である。そして列挙定数を参照した “WeekdayEnum.Sunday” は Enum オブジェクトである。 Enum オブジェクトでは次のメソッドを使用できる。

Enum クラスのメソッド

メソッド 概要
String name() 列挙定数の名前を返す
int ordinal() 列挙定数の順序を返す(0 開始)
toString() 列挙定数の名前を返す
E[] values() 列挙型に含まれるすべての列挙定数を返す

たとえば、次の例は Weekday 列挙型に定義された列挙定数の名前を列挙する。

for (WeekdayEnum w : WeekdayEnum.values()) {
  System.out.println(w.name());
}

コンストラクタ/フィールド/メソッド定義

列挙型もクラスの一種であるため、下位にコンストラクタやフィールド/メソッドを定義することも可能である。

public enum WeekdayEnum {
    Sunday("sun"),
    Monday("mon"),
    Tuesday("tue"),
    Wednesday("wed"),
    Thursday("thu"),
    Friday("fri"),
    Saturday("sat");
 
    // フィールド
    private String name;
 
    // コンストラクタ
    private WeekdayEnum(String name) {
        this.name = name;
    }
 
    // メソッド
    @Override
    public String toString() {
        return this.name;
    }
}

列挙値にその自身の識別子とは別に、たとえば表示用の値を持たせたい場合は、この例のようにフィールド(属性)を宣言する。この例では曜日の短縮名を name フィールドに持つ。 フィールドは通常のクラスと同じようにコンストラクタで初期化できる。構文は基本的にクラスと同じだが、アクセス制限子は private 固定になる点に注意する(したがって、サンプルコードでも private を省略しても意味は同じである)。

コンストラクタを定義した後は、列挙定数もそれに従って列挙定数(引数, …)形式で宣言しなければならない。列挙定義の最後には “;” セミコロンを入れる。

最後にメソッドの定義である。ここでは name フィールドの値を取得できるように toString メソッドを定義する。構文はクラスと同じである。

これで定義した列挙型は次のように利用できる。

System.out.println(WeekdayEnum.Monday.toString());  // 結果 : mon