Javaのインターフェースは「契約」としての役割を持ち、クラスが必ず実装すべきメソッドのシグネチャ(メソッド名、引数、戻り値の型)を定義するための仕組みです。
リモコンのボタンがある程度決まっているように、インターフェースを実装するクラスはその契約に従ってメソッドを実装する必要がある、みたいなイメージです。リモコンインターフェースを利用するクラスは、必ず「電源ボタン」は実装するようにしてね!みたいなことをするのがインターフェースです。

このページではインターフェースって何?という初心者向けにその意味や概念、使い方を1から順を追って解説します。
インターフェース(interface)とは何か
Javaにおけるインターフェースは、「契約(コントラクト)」とも呼ばれ、クラスが必ず提供しなければならないメソッドの名前、引数、戻り値の型を定義する仕組みです。インターフェースで実装すべきメソッドのセットを定義し、そのルールに沿ってクラスが具体的な処理を実装する流れです。
リモコンのボタンの配置がすべての家電で統一されているように、インターフェースは各クラスが持つべき操作を決めています。これにより、どのクラスも同じ操作(メソッド)を持つことが保証され、プログラム全体が一貫した構造となります。
なぜinterfaceが必要なのか
interfaceの基本的な定義と実装
インターフェースは interface キーワードを使って定義します。
例えば、以下は動物が持つべき基本的な動作を示すインターフェースです。
public interface Animal {
// 定数(暗黙的に public static final)
int MAX_AGE = 100;
// 抽象メソッド(暗黙的に public abstract)
void makeSound();
void move();
}
基本的な考え方としてはインターフェースのメソッドは実装を持たず、public abstractが暗黙的に付与されます。実装はクラスが行います。(実践的に例外がありますが、これは後述します。)

よって、void makeSound(){}; と記述してしまうと、これは「何の処理もしない」という意味の実装が定義されてしまうため、コンパイルエラーになります。
また、インターフェースではフィールドの定義は可能ですが、すべてのフィールドは暗黙的にpublic static final(定数)になります。つまり、変数の値を変更することはできません。
interface MyInterface {
int VALUE = 10;
}
// ↑は以下と同じ意味です:
interface MyInterface {
public static final int VALUE = 10;
}
ポイント インターフェースのフィールドの特徴
public(公開)- すべてのクラスからアクセス可能。
static(静的)- インスタンスを作成しなくても利用可能。
final(定数)- 値の変更ができない。
クラスでの実装方法:implements
クラスがインターフェースを実装する際は、implements キーワードを使用します。以下は、Animal インターフェースを実装した Dog クラスの例です。
public class Dog implements Animal {
@Override
public void makeSound() {
System.out.println("ワンワン");
}
@Override
public void move() {
System.out.println("走る");
}
}
実装クラスはインターフェースで定義されたすべてのメソッドを実装する必要があります。インターフェースでは、以下の通り2つのメソッドを実装することを「契約」として定義しているため、そのインターフェースを実装するクラスでは必ず「makeSound()」と「move()」の2つのメソッドを実装しないといけない、ということになります。
尚、メソッドを実装するというのは「メソッドのオーバーライド」をしていると言い換えることもできます。そのため、メソッドのオーバーライドの条件を満たすように実装する必要がある点に注意しましょう。(例えば、アクセス修飾子は同じかより緩くしないといけない等)
| 項目 | 内容 |
|---|---|
| インターフェースのメソッド | 抽象メソッド(中身がない)が基本 |
| 実装クラスでの定義 | 必ず実装する必要がある(@Override推奨) |
| 実際の動作 | オーバーライドとして扱われる |
public interface Animal {
// 定数(暗黙的に public static final)
int MAX_AGE = 100;
// 抽象メソッド(暗黙的に public abstract)
void makeSound();
void move();
}

このようにちゃんと契約を守ったクラスが実装されることを保証するための仕組みがインターフェースです。
インターフェースの継承:extends
Javaでは、インターフェース同士も継承(拡張)が可能です。
クラスの場合は「implements」を使いますが、インターフェース同士の場合は「extends」を使用します。
参考 クラスの継承とは?
インターフェース継承の基本
継承の例
以下は、基本の Animal インターフェースを拡張して、ペット特有の機能を追加する例です。
// 基本の動物の契約
public interface Animal {
void makeSound();
void move();
}
// Animalを拡張して、ペットならではの機能を追加
public interface Pet extends Animal {
void play();
}
この状態で、Pet を実装するクラスは、makeSound()、move() に加えて、play() も実装する必要があります。
public class Cat implements Pet {
@Override
public void makeSound() {
System.out.println("ニャー");
}
@Override
public void move() {
System.out.println("静かに歩く");
}
@Override
public void play() {
System.out.println("ボールで遊ぶ");
}
}
インターフェースの多重継承
インターフェースは複数のインターフェースを同時に継承することも可能です。
たとえば、次のように複数のインターフェースを統合して、新たな契約を定義できます。
public interface Flyable {
void fly();
}
public interface Swimmable {
void swim();
}
// 多重継承:BirdはAnimal、Flyable、Swimmableのすべての契約を引き継ぐ
public interface Bird extends Animal, Flyable, Swimmable {
// 追加のメソッドを定義することも可能
void layEggs();
}
このように、クラスが Bird インターフェースを実装すれば、makeSound()、move()、fly()、swim()、layEggs() のすべてを実装する必要があります。

以上がJavaのインターフェースの基本です。ここからは、この基本を押さえたうえでの実践編の解説に進みます。
インターフェースに実装できるメソッドとその他実践例
基本的に、インターフェースのメソッドは抽象的(具体的な実装を持たない)ですが、Java 8以降では一部例外が存在します。ここからはそれらのメソッドについてご説明します。
defaultメソッド
Java 8以降、インターフェースは default メソッドを持つことができ、実装クラスで必ずオーバーライドしなくても動作する既定の処理を提供できるようになりました。
これは、インターフェースを拡張して新たなメソッドを追加する際、既存の実装に影響を与えないようにするために非常に有用です。
public interface Greeting {
void sayHello();
default void sayGoodbye() {
System.out.println("さようなら");
}
}
default を付与することで、「sayGoodbye()」メソッドは実装クラスでオーバーライドしなくても動作する既定の処理を行うようになります。「オーバーライドしてもよいけど、オーバーライドしなかったらこういう動きね!」をやりたいときに使うのがdefaultメソッドです。
ちなみに、defaultメソッドもインターフェースに定義するメソッドと同様に、自動的にpublicで修飾されます。
staticメソッド
また、インターフェース内で static メソッドを定義することで、インターフェースに関連するユーティリティ処理をまとめることができます。(参考 staticとは?)
これらは実装クラスに依存せず、インターフェース名を通じて直接呼び出せます。
interface MathUtil {
static int square(int x) {
return x * x;
}
}
public class InterfaceStaticTest {
public static void main(String[] args) {
int result = MathUtil.square(5);
System.out.println(result); // 出力: 25
}
}
MathUtil.square(5) のように、インターフェース名.メソッド名() で呼び出せます。
- クラスのようにインスタンス化不要
staticメソッドはインターフェースのインスタンスを作らずに呼び出せる。
- オーバーライド不可
- 実装クラスでは
staticメソッドをオーバーライドできない。
- 実装クラスでは
publicで定義するのが一般的private static(Java 9以降)も可能だが、外部からは呼べない。
プライベートメソッド(private)
Java 9以降、インターフェースにprivateメソッドを定義できるようになりました。これは、デフォルトメソッド(default)やstaticメソッドのコードを整理するために使われます。
interface MyInterface {
default void showMessage() {
System.out.println(getGreeting()); // privateメソッドを呼び出す
}
private String getGreeting() { // privateメソッド
return "こんにちは!";
}
}
public class PrivateMethodTest implements MyInterface {
public static void main(String[] args) {
PrivateMethodTest test = new PrivateMethodTest();
test.showMessage(); // 出力: こんにちは!
}
}
getGreeting() は privateなので外部から直接呼べないが、defaultメソッド内で利用可能になります。
interface Utility {
static void printMessage() {
System.out.println(getStaticGreeting());
}
private static String getStaticGreeting() {
return "Hello from private static!";
}
}
public class StaticMethodTest {
public static void main(String[] args) {
Utility.printMessage(); // 出力: Hello from private static!
}
}
getStaticGreeting() は private static なので、printMessage()の内部でのみ使用可能になります。
- 外部や実装クラスからは呼び出せない
privateなので、インターフェース内部でのみ利用可能。
defaultメソッドやstaticメソッドの共通処理をまとめる- コードの重複を防ぎ、メンテナンス性を向上させる。
defaultメソッドから呼び出し可能defaultメソッド内で処理を共通化できる。
インターフェースと抽象クラスの使い分け
名前の衝突とデフォルトメソッドの対処
複数のインターフェースを実装または継承している場合、同じシグネチャの default メソッドが存在するときは、実装クラス側で明示的にオーバーライドして衝突を解決する必要があります。
public interface A {
default void greet() {
System.out.println("こんにちは from A");
}
}
public interface B {
default void greet() {
System.out.println("こんにちは from B");
}
}
public class MyClass implements A, B {
@Override
public void greet() {
// 必要に応じてどちらか、または独自の処理を実装
System.out.println("こんにちは from MyClass");
}
}
コーディングの実践的なアドバイス

インターフェースの基本的な理解と継承の仕組みを押さえておくことで、将来的に大規模なプログラムやフレームワークを設計・開発する際にも、柔軟で再利用性の高いコードを書くことが可能となります。まずはシンプルな例から実際に手を動かし、徐々に複雑な設計にも挑戦してみてください。
