はじめに
Javaのimplementsは、クラスにインターフェースの契約を実装させるためのキーワードです。初心者がJavaプログラミングでつまずきやすいのは、extendsとの違い、publicの付け忘れ、抽象メソッドの実装漏れが同時に出てくる点になります。
そのため、Javaでは「インターフェースで外側の形を決め、クラスで具体的な処理を書く」と整理すると理解しやすくなります。サンプルコードを読みながら、interface、class、implements、@Override、publicの関係を確認してください。
- Java SE 21 / OpenJDK 21
- コマンドライン実行を想定し、GUI例のみ Swing を使用
- Javaで
implementsを使う基本構文 - インターフェースと抽象クラスの使い分け
- 複数インターフェース、デフォルトメソッド、ジェネリクスの扱い
- 初心者が遭遇しやすいコンパイルエラーの原因
- 実務的な設計に近いサンプルコードの読み方
Javaとimplementsの基本概念
結論から言うと、Javaでimplementsを使う場面は、クラスに「このメソッドを持つ」という約束を守らせたい場合です。たとえばRunnableを実装するクラスはrunを持つため、呼び出し側は具体的なクラス名に依存せず処理を扱えます。
結果: 期待される出力は「作業を実行」です。
Javaとは
Javaは、クラスを中心にプログラムを組み立てるオブジェクト指向のプログラミング言語です。一般に、Javaで書いたプログラムはjavacで.classへコンパイルされ、javaコマンドからJava仮想マシン上で動作します。
その仕組みにより、OSごとの差をJava仮想マシンが吸収しやすくなります。公式ドキュメントによれば、Javaの言語仕様はThe Java Language Specificationで定義され、標準APIはJava SE 21 API Documentationから確認できるのが基本です。
これらの仕様を細部まで読む必要はありませんが、interface、abstract、default、staticなどの意味に迷ったときは一次情報を参照すると判断が安定します。初心者向けの入門ではJava List型完全ガイドやJavaのオーバーライド解説と合わせて読むと、Javaプログラミングの全体像をつかみやすいでしょう。
implementsキーワードとは
implementsは、クラスがインターフェースを実装することを宣言するキーワードです。インターフェース側にはメソッドの名前、引数、戻り値といったsignatureが並び、実装クラス側が処理の中身を補います。
その関係は、契約書と実作業の関係に近いと考えられます。Animalにbarkが定義されていれば、Dogはbarkを持つ必要があり、呼び出し側はAnimal型として扱えますし、ここがポイントです。
ただし、Javaのインターフェースは単なる抽象メソッドの集合だけではありません。Java 8以降はdefaultメソッドとstaticメソッドを持てるため、後方互換性を保ちながらAPIを拡張する設計にも使われます。
| 要素 | 役割 | 主な構文 | 初心者の注意点 |
|---|---|---|---|
| インターフェース | クラスが持つべき操作の形を決める | interface Animal | 処理本体をクラス側に書く |
| 実装クラス | インターフェースの契約を満たす | class Dog implements Animal | 抽象メソッドを漏れなく実装する |
| 抽象メソッド | 実装を要求するメソッド | void bark() | シグネチャを一致させる |
| オーバーライド | 親側の宣言に対応する処理を書く | @Override | 注釈でミスを検出しやすくする |
| 複数実装 | 複数の契約を同時に満たす | implements A, B | 同名メソッドの扱いを確認する |
| 抽象クラス | 状態と共通処理を持たせる | abstract class | クラス継承は原則ひとつだけ |
| デフォルトメソッド | インターフェースに標準処理を置く | default void run() | 衝突時は明示的に上書きする |
| ジェネリクス | 型を引数のように扱う | Storage<T> | 型安全性を保つ |
implementsの詳細な使い方
Javaのimplementsは、class クラス名 implements インターフェース名の形で書きます。この書き方を覚えたうえで、単一実装、複数実装、抽象クラスとの違い、デフォルトメソッドの順に確認すると、サンプルコードの意図が追いやすくなります。
具体的には、newで生成した具象クラスをインターフェース型の変数へ代入できる点が中心になるのが目安です。そのため、Dog myDog = new Dog()だけでなく、Animal animal = new Dog()という書き方にも慣れておくと、Javaプログラミングの設計を読みやすくなります。
サンプルコード1:単純なインターフェースの実装
最小構成では、インターフェースにメソッドをひとつ置き、クラス側でそのメソッドを実装します。このサンプルコードではAnimalが契約、Dogが具体的な処理を持つクラスです。
結果: 期待される出力は「ワンワン」です。
このときbarkはAnimalで宣言され、Dogで処理内容が決まります。初心者はpublicを省略しがちですが、インターフェース由来のメソッドは公開範囲を狭められないため、実装側ではpublic void bark()と書きます。
サンプルコード2:複数のインターフェースを実装
Javaはクラスの多重継承を認めませんが、インターフェースの複数実装は可能です。これにより、Animalとしての動作とPetとしての動作を同じDogへ持たせられますが、これは押さえたい点です。
結果: 期待される出力は「ワンワン」と「しっぽを振る」です。
この書き方では、implements Animal, Petのようにカンマでインターフェースを並べます。一方で、実装するメソッドが増えるほどクラスの責務も膨らむため、ひとつのクラスに役割を集めすぎない設計が現実的です。
サンプルコード3:インターフェースのメソッドをオーバーライド
インターフェースへメソッドを追加すると、そのインターフェースを実装しているクラスにも対応が求められます。@Overrideを付けると、メソッド名や引数の型がずれた場合にコンパイラが検出しやすくなるのがポイントです。
結果: 期待される出力は「ワンワン」と「走る」です。
この例ではbarkとrunの両方を実装しているため、DogはAnimalの契約を満たします。逆にどちらかを省くと、Dogを通常の具象クラスとしてコンパイルできません。
サンプルコード4:抽象クラスとの違い
抽象クラスは、共通の状態や処理を継承させたい場合に向いています。一方、インターフェースは「何ができるか」を型として表す用途に向いており、extendsとimplementsの選択で設計意図が変わりますし、これが一つの目安です。
結果: 期待される出力は「ポチがワンワンと吠える」です。
このサンプルコードでは、AnimalAbstractがnameという状態を持ち、Dogがsuper(name)で初期化を引き継ぎます。ただし、Javaではクラスの継承元を複数指定できないため、共通能力を横断的に表したい場合はインターフェースのほうが扱いやすくなります。
サンプルコード5:デフォルトメソッドの利用
Java 8以降のインターフェースでは、defaultを使ってメソッド本体を持たせられますが、覚えておくと役立つでしょう。既存の実装クラスを壊さずに共通処理を追加したいときに、この仕組みが役立ちます。
結果: 期待される出力は「ワンワン」と「動物が走る」です。
この場合、Dogはbarkだけを実装し、runはインターフェース側の既定処理を使います。ただし、クラス独自の走り方を表したい場合は、public void run()を再定義して上書きできます。
💡 Tips: @Overrideは動作に必須ではありませんが、メソッド名の打ち間違いや引数の型違いを早く見つける助けになるのが一般的です。Java初心者ほど付けておくと読み違いを減らせます。implementsの応用例
Javaのimplementsは、単純な練習用クラスだけでなく、標準ライブラリ、GUIイベント、デザインパターン、業務ルールの分離にも使われます。これらはすべて「呼び出し側はインターフェースを見る」という同じ考え方に基づきますし、ここを基本と考えるとよいでしょう。
そのため、サンプルコードごとの文法差よりも、変数の型がListやPaymentStrategyになっている点へ注目すると理解しやすくなります。具体的なクラスを差し替えられることが、Javaプログラミングでインターフェースを使う大きな理由です。
サンプルコード6:コレクションフレームワークでの利用例
Javaのコレクションでは、ListやSetやMapが代表的なインターフェースです。変数をArrayListではなくListで受けると、後から別の実装へ変えやすくなります。
結果: 期待される出力は「Apple」「Banana」「Cherry」の順です。
このサンプルコードでは、List<String>が操作の入口になり、実体としてArrayList<>を生成しています。配列や繰り返し処理も合わせて学ぶ場合は、Java List型完全ガイドを参照するとつながりが見えます。
サンプルコード7:イベントリスナーとしての使用例
GUIのイベント処理でも、インターフェースを実装したクラスがよく登場するのが現実的です。SwingのActionListenerは、ボタン操作を受け取るためにactionPerformedを実装する構造です。
結果: 期待される表示は、ボタンを押した後にラベルが「Clicked!」へ変わる状態です。
この例ではbutton.addActionListener(this)により、現在のオブジェクトがイベントの受け手になります。ただし、SwingはデスクトップGUI環境を前提にするため、サーバーやオンライン実行環境ではウィンドウが表示されない場合があります。
サンプルコード8:ストラテジーパターンにおける利用例
ストラテジーパターンでは、アルゴリズムをインターフェースとして切り出し、実装クラスを差し替えますし、ここがポイントです。支払い方法、並び替え方法、通知方法のように処理の種類が増えやすい領域で使いやすい構造です。
結果: 期待される出力は「クレジットカードで3000円支払いました。」と「現金で5000円支払いました。」です。
このとき呼び出し側はPaymentStrategyだけを見ており、CreditCardPaymentとCashPaymentの内部差分を知る必要がありません。こうした分離は、Javaでテストしやすい設計を作るときにも使われます。
サンプルコード9:ユーザー定義インターフェースの作成
独自の業務ルールを扱う場合も、インターフェースを自作できます。挨拶、計算、ファイル出力など、処理の入口だけを先に決めておくと、具体的な実装を後から追加しやすくなると整理できます。
結果: 期待される出力は「Hello, John!」と「こんにちは、太郎さん!」です。
このサンプルコードでは、Greeting型の変数に異なる実装を代入しています。初心者はクラス名で変数を宣言しがちですが、変更に強いJavaプログラミングではインターフェース型で受ける形がよく使われます。
サンプルコード10:implementsとジェネリクス
ジェネリクスを使うと、インターフェースの利用対象となる型を外から渡せますが、これは押さえたい点です。Storage<T>のように書くと、String用、Integer用、独自クラス用へ同じ設計を展開できます。
結果: 期待される出力は「Java」です。
この例では、Storage<String>によりaddの引数とgetの戻り値がStringにそろいます。そのため、不要なcastを避けながら、型の不一致をコンパイル時に検出できます。
Tそのものを直接生成する設計には注意が必要です。Javaでは型安全性を高める目的で使う、と整理すると扱いやすくなると理解できます。注意点と対処法
Javaでimplementsを使う際のエラーは、構文そのものよりも契約の不一致から起きることが多くなります。特に押さえたいのは、メソッドのシグネチャ、アクセス修飾子、複数インターフェースで同名メソッドが出る場合の扱いです。
そのため、エラー文を見たら、method名、return type、引数リスト、publicの有無を順番に確認します。関連してアノテーションの使い方を深めたい場合は、Javaアノテーションの解説も参考になると覚えるとよいでしょう。
メソッドのシグネチャに注意
インターフェースのメソッドを実装するときは、メソッド名、引数の型と並び、戻り値の型をそろえる必要があります。次の例ではshow(String msg)を求めるインターフェースに対し、クラス側がshow(int msg)を書いているため一致しません。
結果: 期待される状態はコンパイルエラーです。WrongDisplayはDisplayのshow(String)を実装していません。
この問題は、public void show(String msg)へ修正すると解消できます。@Overrideを付けておけば、意図したオーバーライドではないことをコンパイラが早めに示します。
アクセス修飾子の注意点
インターフェースの抽象メソッドは暗黙的にpublicです。そのため、実装クラスでpublicを外すとアクセス範囲を狭めることになり、Javaのコンパイル規則に反すると考えられます。
結果: 期待される状態はコンパイルエラーです。speakのアクセス範囲がpublicより狭いためです。
この場合はpublic void speak()へ変更します。初心者が見落としやすい点ですが、インターフェース実装ではprivateやパッケージプライベートにできないと覚えるとよいでしょう。
ダイヤモンド問題とその対処法
複数のインターフェースが同じ抽象メソッドを持つ場合、実装クラスでひとつのメソッドを書けば契約を満たせます。メソッドの形が同じなら、呼び出し側の型がEngineでもVehicleでも同じ処理へ到達すると言えるでしょう。
結果: 期待される出力は「Car started」です。
ただし、同名のdefaultメソッドが複数のインターフェースにある場合は、実装クラス側で明示的に上書きする必要があります。抽象メソッドだけの同名衝突と、デフォルトメソッドの衝突は扱いが異なるため注意してください。
implementsのエラーを直すときに、インターフェース側の定義を安易に変えると他の実装クラスへ影響します。共有APIでは、実装クラス側の不足を直す判断が先になるのが基本です。カスタマイズ方法
Javaでインターフェースの基本が理解できたら、拡張、デフォルトメソッドの上書き、自作インターフェースの設計に進むと応用しやすくなります。どの方法でも、呼び出し側が見る型と、実際に動くクラスを分けて考える姿勢が軸になります。
一方、カスタマイズを増やしすぎると、インターフェースの責務が広がって読みにくくなるのが目安です。小さく分けたインターフェースを組み合わせる設計を意識すると、変更範囲を読み取りやすくなります。
インターフェースの拡張
インターフェースはextendsで別のインターフェースを拡張できます。クラスの継承と違い、インターフェース同士では複数拡張も可能ですが、読みやすさを優先して責務を絞るのが一般的です。
結果: 期待される出力例は、setColor("赤")の後にdraw()を呼ぶ場合の「赤の四角形を描画します。」です。
この例ではColoredShapeがShapeを拡張し、drawに加えてsetColorを要求します。その結果、Squareは描画と色設定の両方を実装する必要があるのが一般的です。
デフォルトメソッドのオーバーライド
デフォルトメソッドはそのまま使うだけでなく、実装クラスで上書きできます。共通の標準動作を持たせながら、必要なクラスだけ動作を変えたい場合に自然な書き方です。
結果: 期待される出力は、JapaneseGreeterのgreet()を呼んだ場合の「こんにちは、世界!」です。
この上書きにより、Greeterの標準実装ではなくクラス側の処理が選ばれます。なお、複数のインターフェースで同じデフォルトメソッドがある場合は、クラス側で明示的に解決する必要があります。
自作インターフェースでの応用
自作インターフェースは、チームや教材で共通のルールを表すときにも使えるのが現実的です。たとえば計算処理をCalculatorとして定義しておけば、単純な加算、税計算、割引計算などへ実装を分けられます。
結果: 期待される戻り値は、add(3, 4)を呼んだ場合の7です。
このサンプルコードでは、Calculatorが計算の入口を決め、SimpleCalculatorが加算の中身を持ちます。条件分岐や日付処理と組み合わせる場合は、Javaでうるう年を判定する解説やJavaエスケープ処理の解説も文法理解の補助になります。
💡 Tips: 自作インターフェース名は、Readable、Sortable、PaymentStrategyのように役割が伝わる名前にすると、実装クラスの責務が読み取りやすくなると整理できます。
まとめ
Javaのimplementsは、インターフェースで決めた契約をクラスに実装させるための構文です。単純なAnimalの例から、List、ActionListener、ストラテジーパターン、ジェネリクスまで、同じ考え方で読み解けます。
その理解の中心にあるのは、変数の型をインターフェースにして、実体となるクラスを差し替えられるようにすることです。Javaプログラミングでは、この分離によりテスト、拡張、保守の見通しがよくなります。
ただし、implementsを使えば設計が必ず良くなるわけではありません。メソッドが多すぎるインターフェース、責務が広すぎる実装クラス、目的が曖昧なdefaultメソッドは、かえって変更を難しくする場合があると理解できます。
そのため、初心者はinterfaceで約束を決め、classで処理を書き、@Overrideで対応関係を明示する流れから練習するとよいでしょう。サンプルコードを小さく動かしながら、public、void、return、String、int、private、new、for、importなどの周辺構文も合わせて確認してください。
関連記事
- Java List型完全ガイド!初心者でもマスターできる7つのステップ
- Javaアノテーションの12選!初心者から上級者まで徹底ガイド
- Javaでうるう年を判定!初心者でも分かる9ステップ解説
- Javaエスケープ処理の10ステップマスターガイド
- Javaでマスターする!オーバーライドのたった7つのステップ
※本記事は実在のエンジニア複数名で構成される Japanシーモア編集部が、AI支援を活用して作成・校正・公開しています。


