Javaプログラミング入門 10章 [クラスメンバと修飾子]

Java

こんにちは。ECF Techブログ
担当 Michiharu.Tです。

Javaプログラミング入門記事の第10章をお送りいたします。
第10章のテーマは「クラスメンバと修飾子」です。

本連載の初回および章立ての一覧については下記のリンクから確認できます。

Javaプログラミング入門 0章
0章 Javaプログラミングを始めよう こんにちは。ECF Techブログ 担当 Michiharu.Tです。 この記事はプログラミング言語のJavaを、実際に動かしながら学びたい人のための学習教材となっています。手を多く動かすこと、感覚を...

解説動画

2024/02/09 解説動画を掲載しました。

10-1 修飾子の基本

修飾子は、Javaを構成する要素の定義部分に追加情報を付与するためのものです。これまでも修飾子はいくつか登場しています。例えば下記のMainクラスの定義におけるpublicは修飾子の1つです。

public class Main

また、次のmainメソッドにおけるpublicstaticも修飾子です。

public static void main(String[] args)

修飾子の特徴をいくつか示します。

  • 修飾子はクラス、メソッド、フィールドなどの定義部分の先頭に付記できます。
  • 修飾子は定義部分に必須ではありません。
  • 修飾子は複数付記できます。

本章では次の2つの修飾子を扱います。

  • final修飾子
  • static修飾子

10-2 クラスフィールド

10-2-1 クラスフィールドとは

初めにインスタンスごとに情報を持つことが適切ではないケースについて考えます。たとえば商品(Item)クラスに消費税率を保持することを考えてみましょう。

その方法として、Itemクラスに消費税率を表すtaxをフィールドとして持たせたとします(下図)。

インスタンスの関連

ですが、この方法は次の2つの理由から適切ではありません。

  • 消費税率は通常、りんごは5%、みかんは8%のように商品(インスタンス)ごとに変わるものではない。
  • インスタンスごとに消費税率を保持してしまうと、消費税率が変更になった場合に、生成済みのすべてのインスタンスの税率を変更しなければならない。

クラスフィールドはこのような情報を保持する際に有効な手段の1つです。先にクラスフィールドの定義方法を示します。

static フィールド宣言;

これまでのフィールド宣言の前にstatic修飾子を付記します。また、クラスフィールドを利用する記述は次のようになります。

クラス名.フィールド名

staticがついたフィールドの性質・動作については、次のプログラムで説明します。

プログラム(Item.java)

public class Item{
    static double tax = 0.1;    //消費税率
    String name;    //名前
    int price;      //価格

    //コンストラクタ
    Item(String name, int price){
        this.name = name;
        this.price = price;
    }

    void display(){
        System.out.println("商品名:" + name + " 価格:" + price);
        System.out.println("消費税:" + (int)(price*Item.tax));
    }
}
  • 2行目でstaticつきのフィールドtaxを定義しています。初期値に0.1が代入されています。
  • 3,4行目に通常のフィールドnamepriceが定義されています。
  • コンストラクタは引数から受け取った値を各フィールドに代入しています。
  • displayメソッドは、商品名、価格、消費税の金額を表示しています。

次に、Item.javaを利用するメインクラスを示します。

プログラム(Main.java)

public class Main {
    public static void main(String[] args) {
        Item ringo = new Item("りんご",150);
        Item mikan = new Item("みかん",200);

        ringo.display();
        mikan.display();
    }
}

実行結果

商品名:りんご 価格:150
消費税:15
商品名:みかん 価格:200
消費税:20

解説
Main.javaの4行目までが実行された時点のイメージを下に示します。

10-2イメージ

図に示すとおり、通常のフィールドはインスタンスごとにコピーが作成されるのに対し、クラスフィールドは特定の領域にただ1つ作成されます。その名前のとおり、クラスそのものが持つフィールドと考えると良いでしょう。そのため、クラスごとの情報を保持したい場合に適したフィールドと言えます。

Itemクラスのdisplayメソッドでは、そのクラスフィールド(Item.tax)を使って、下記のように消費税の計算を行っています。

System.out.println("消費税:" + (int)(price*Item.tax));

Item.taxが表すのは、特定の領域に保持されているただひとつの値0.1です。そのため、Main.javaの6,7行目のようにどのインスタンスのdisplayメソッドを呼び出しても、消費税率として0.1を使って計算が行われます。

10-2-2 クラスフィールドの操作

このようにインスタンスごとに保持しない情報をクラスフィールドに設定しておくことで、修正も容易になります。次のプログラムは、消費税率が10%(0.1)の場合と消費税率が5%(0.05)の場合の消費税額の違いを表示したものです。

プログラム(Main.java)

public class Main {
    public static void main(String[] args) {
        Item ringo = new Item("りんご",150);
        Item mikan = new Item("みかん",200);

        System.out.println("---税率10%---");
        ringo.display();
        mikan.display();

        System.out.println("---税率5%---");
        Item.tax = 0.05;
        ringo.display();
        mikan.display();
    }
}

実行結果

---税率10%---
商品名:りんご 価格:150
消費税:15
商品名:みかん 価格:200
消費税:20
---税率5%---
商品名:りんご 価格:150
消費税:7
商品名:みかん 価格:200
消費税:10

解説
11行目で消費税率を0.05に変更し、再度商品情報を表示しています。1箇所の修正で2つの商品の税率が5%で計算されていることがわかります。

クラスフィールドは自クラス、他クラス関係なく、どのクラスからでもクラス名.フィールド名で表します。

10-3 クラスメソッド

メソッドもフィールドと同様、定義部分にstaticを付記することでクラスメソッドとして定義できます。クラスフィールド同様、クラスそのものがもつメソッドと考えると良いでしょう。文法は次のようになります。

クラスメソッドの定義

static メソッド定義

クラスメソッドの利用

クラス名.メソッド名(引数...)

次のプログラムで動作の様子を確認します。

プログラム(Item.java)

public class Item{
    static double tax = 0.1;    //消費税率
    String name;    //名前
    int price;      //価格

    //コンストラクタ
    Item(String name, int price){
        this.name = name;
        this.price = price;
    }

    //クラスメソッド
    static void showTax(){
        System.out.println("---税率:" + (int)(Item.tax*100) + "%---");
    }

    void display(){
        System.out.println("商品名:" + name + " 価格:" + price);
        System.out.println("消費税:" + (int)(price*Item.tax));
    }
}

13行目にクラスメソッドshowTaxを定義しています。クラスフィールドtaxを使って税率を表示するメソッドです。%表示するため100をかけています。計算結果をそのまま表示すると10.0%のように、小数点表示になってしまうためint型にキャストしています。

プログラム(Main.java)

public class Main {
    public static void main(String[] args) {
        Item ringo = new Item("りんご",150);
        Item mikan = new Item("みかん",200);

        //クラスメソッドの呼び出し        
        Item.showTax();
        ringo.display();
        mikan.display();
    }
}

実行結果

---税率:10%---
商品名:りんご 価格:150
消費税:15
商品名:みかん 価格:200
消費税:20

解説
7行目でクラスメソッドを呼び出し、税率を表示しています。クラスメソッドもクラスフィールド同様、クラスそのものが持つメソッドを定義する際に有効です。

10-3-1 クラスの構成要素の整理

クラス内に定義可能な要素が増えてきましたので、ここで一旦下図を使って整理をしたいと思います。

  • クラスの構成要素は大きくフィールドコンストラクタメソッドの3つです。
  • staticがつかないフィールドやメソッドは、クラスフィールド、クラスメソッドと区別してインスタンスフィールドインスタンスメソッドという事もあります。
  • クラスフィールド、クラスメソッドをまとめてクラスメンバ。インスタンスフィールド、インスタンスメソッドをまとめてインスタンスメンバ。という事もあります。

10-4 final修飾子

Item.javaにクラスフィールドとして定義した消費税率などの値は、通常プログラム中に頻繁に変わるものではありません。場合によっては、後から変更されたくない。という事もあるでしょう。このようなフィールドはfinal修飾子を付記して定数フィールドとしておくことができます。定数フィールドは、値を変更できない性質を持つフィールドのことを指す言葉です。

プログラム例を示します。

プログラム(Item.java)

public class Item{
    static final double TAX = 0.1;    //消費税率
}

プログラム(Main.java)

public class Main{
    public static void main(String[] args){
        Item.TAX = 0.2;
    }
}

コンパイル結果

Main.java:3: エラー: static final変数TAXに値を割り当てることはできません
                Item.TAX = 0.2;

解説

  • TAXフィールドにはfinalが付記されています。これがfinal修飾子です。
  • 必須ではありませんが、staticfinalを同時に使用する場合の順番は、上記が推奨されます。
  • final修飾子を付記した定数フィールドの名前はすべて大文字とするのが慣例となっています。

フィールドTAXはfinalが付くことで定数フィールドとなったため、値を変更するとエラーとなります。Main.javaの3行目では、Item.TAX = 0.2;の記述で値を代入しようとしているため、エラーとなります。

タイトルとURLをコピーしました