Java入門 #23 - インターフェース

入門 | 10分 で読める | 2026.05.02

公式ドキュメント

今回やること

インターフェースは、クラスが提供する操作の契約です。内容が違うReportLabelへ「印刷できる」という共通のPrintable契約を付けます。

前提: Java入門 #21 - 継承#22 - ポリモーフィズムを終えていること。

Printable契約: printBody()を持つ
├── Report implements Printable
└── Label  implements Printable

1. 契約を宣言する

interface Printable {
    void printBody();
}

本体のないprintBody()は、実装クラスが必ず用意する操作です。インターフェース内の抽象メソッドは暗黙にpublic abstractですが、入門では短い形を使います。

インターフェース自体はnew Printable()で作れません。契約を実装したクラスのオブジェクトを作ります。

2. implementsで実装する

class Report implements Printable {
    @Override
    public void printBody() {
        System.out.println("月次レポート");
    }
}

implements Printableと書いた具体クラスは、printBody()を実装します。インターフェースのメソッドはpublicなので、実装側もpublicが必要です。

@Overrideを付けると、名前や引数を間違えた時にコンパイラが検出します。

3. defaultメソッドを一つ追加する

defaultを付けると、インターフェースに共通の実装を置けます。

default void printHeader() {
    System.out.println("--- 印刷開始 ---");
}

実装クラスは、そのまま共通処理を利用できます。すべてをdefaultにせず、共通して同じ動きになる小さな処理に使います。

完成コードを動かす

InterfaceDemo.javaとして保存します。

interface Printable {
    void printBody();

    default void printHeader() {
        System.out.println("--- 印刷開始 ---");
    }
}

class Report implements Printable {
    @Override
    public void printBody() {
        System.out.println("月次レポート");
    }
}

class Label implements Printable {
    @Override
    public void printBody() {
        System.out.println("配送ラベル");
    }
}

public class InterfaceDemo {
    public static void main(String[] args) {
        Printable[] items = {new Report(), new Label()};

        for (Printable item : items) {
            item.printHeader();
            item.printBody();
        }
    }
}
javac InterfaceDemo.java
java InterfaceDemo

配列の型をPrintableにすると、元のクラスが異なる2つを同じ「印刷できるもの」として扱えます。呼び出せる操作はPrintableの契約にあるものです。

抽象クラスとの短い違い

欲しいもの選択の目安
異なる種類へ同じ操作を約束したいインターフェース
密接な親子で状態やコンストラクタを共有したい抽象クラス

Javaのクラスは複数のインターフェースを実装できます。一方、クラスの直接継承は1つです。抽象クラスの具体例は次の記事で扱います。

成功確認

--- 印刷開始 ---
月次レポート
--- 印刷開始 ---
配送ラベル

2クラスが同じPrintable型として扱われ、共通headerと個別bodyを表示できれば成功です。

よくあるつまずき

実装メソッドへpublicを付けない

インターフェースのpublicメソッドを、より狭いアクセス範囲にはできません。実装側をpublicにします。

interfaceを直接newする

契約だけでは実体を作れません。new Report()のように実装クラスを作り、Printable型の変数へ代入します。

共有状態までinterfaceへ持たせる

インターフェースのフィールドは定数です。オブジェクトごとの状態やコンストラクタを共有したいなら、次の抽象クラスを検討します。

練習

Playableインターフェースにplay()とdefaultのshowReady()を定義し、MusicVideoで実装してください。Playable[]から両方を呼びます。

次のステップ

Java入門 #24 - 抽象クラスで、共通状態と未実装メソッドを同じ親クラスへ置く方法を学びます。

参考リソース

← 一覧に戻る
PR
PR
PR
PR