Javaのデフォルトメソッド完全解説!初心者が理解すべき基本ルール
生徒
「Javaのインタフェースにメソッドの実装を書いているコードを見たんですが、それって正しいんですか?」
先生
「いい質問ですね!インタフェースでは基本的に抽象メソッドしか定義できませんが、デフォルトメソッドという機能を使うと実装を持つことができます。詳しく見ていきましょう!」
1. デフォルトメソッドとは?
デフォルトメソッドは、Java 8で導入されたインタフェースの機能です。defaultキーワードを使うことで、インタフェースに実装を記述できます。これにより、実現クラスに共通の動作を提供できます。
以下はデフォルトメソッドの基本例です:
public interface Greetable {
default void greet() {
System.out.println("Hello, default method!");
}
}
このようにdefaultキーワードを使えば、インタフェースに共通の処理を記述できます。
2. 実現クラスでデフォルトメソッドを使用する
実現クラスはデフォルトメソッドをそのまま利用できます。以下に、デフォルトメソッドを実現するクラスの例を示します:
public class Greeter implements Greetable {
// デフォルトメソッドをオーバーライドせず、そのまま使用
}
public class Main {
public static void main(String[] args) {
Greetable greeter = new Greeter();
greeter.greet(); // 出力: Hello, default method!
}
}
このコードでは、GreeterクラスがGreetableを実現しており、デフォルトメソッドgreetをそのまま使用しています。
3. デフォルトメソッドのオーバーライド
実現クラスでデフォルトメソッドをオーバーライドして独自の実装を提供することも可能です。以下にその例を示します:
public class CustomGreeter implements Greetable {
@Override
public void greet() {
System.out.println("Hello from CustomGreeter!");
}
}
public class Main {
public static void main(String[] args) {
Greetable greeter = new CustomGreeter();
greeter.greet(); // 出力: Hello from CustomGreeter!
}
}
このコードでは、CustomGreeterクラスがGreetableのgreetメソッドをオーバーライドしています。
4. 複数インタフェースのデフォルトメソッド
クラスが複数のインタフェースを実現しており、それらが同じ名前のデフォルトメソッドを持つ場合、競合が発生します。このとき、クラス側でどの実装を使うかを明示的に指定する必要があります。
public interface A {
default void show() {
System.out.println("Default method from A");
}
}
public interface B {
default void show() {
System.out.println("Default method from B");
}
}
public class C implements A, B {
@Override
public void show() {
A.super.show(); // Aのデフォルトメソッドを呼び出す
}
}
public class Main {
public static void main(String[] args) {
C obj = new C();
obj.show(); // 出力: Default method from A
}
}
このように、インタフェース名.super.メソッド名()で特定のデフォルトメソッドを明示的に呼び出します。
5. 試験対策ポイント
defaultキーワードを使ってデフォルトメソッドを定義する。- 複数のインタフェースのデフォルトメソッドが競合した場合、
superを使って解決する。 - デフォルトメソッドはオーバーライド可能。
まとめ
本記事では、Javaのデフォルトメソッド(default method)について学びました。
デフォルトメソッドを活用すると、インタフェース側に共通処理を持たせられるため、実現クラス(implementsするクラス)での重複コードを削減できます。
また、既存のインタフェースにメソッドを追加しても、実装クラスをすべて修正せずに済むケースがあり、設計の拡張に強いのが特徴です。
重要なポイントは、デフォルトメソッドは「インタフェースなのに実装を持てる」という点です。
必要に応じて実装クラス側でオーバーライドでき、さらに複数インタフェースを実現したときに同名メソッドが存在して競合した場合でも、
インタフェース名.super.メソッド名()の形で呼び出し先を明示できます。
defaultキーワードの意味を押さえておくと、Javaのインタフェース設計をより実用的に組み立てられるようになります。
インタフェース名.superで解決できます。
次のサンプルコードは、デフォルトメソッドの実践的な使い方を示しています(フォーマット処理をインタフェース側に寄せ、出力側で再利用しています)。
public interface Printer {
default void print(String message) {
System.out.println("Printing: " + message);
}
}
public interface Formatter {
default String format(String message) {
return "[Formatted] " + message;
}
}
public class ConsolePrinter implements Printer, Formatter {
@Override
public void print(String message) {
System.out.println(format(message)); // Formatterのメソッドを活用
}
}
public class Main {
public static void main(String[] args) {
Printer printer = new ConsolePrinter();
printer.print("Hello, Java!");
}
}
実行結果:
[Formatted] Hello, Java!
- デフォルトメソッドはインタフェースに実装(処理)を持たせられる。
- 実装クラスでは必要に応じてオーバーライドできる。
- 同名メソッドが複数インタフェースで競合した場合は明示的に解決できる。
生徒
「デフォルトメソッドって、普通のクラスのメソッドみたいに感じますね。インタフェースにこんな機能があるなんて驚きました!」
先生
「そうですね。デフォルトメソッドのおかげで、インタフェースが柔軟に使えるようになりました。 特に、既存のインタフェースに新しいメソッドを追加したいときに役立ちます。 実装クラスを全部修正しないといけない状況を減らせるので、保守性の面でもメリットが大きいですよ。」
生徒
「確かに!でも、複数のインタフェースに同じ名前のメソッドがあるときの競合解決は少し複雑ですね。」
先生
「その通りです。ただ、インタフェース名.super.メソッド名()を使えば、どのメソッドを呼び出すか明確に指定できます。
“どこに共通処理を置くか”と合わせて考えると、デフォルトメソッドの使いどころが分かりやすくなります。実際に試して慣れていきましょう!」