割と普通なブログ

Microsoft Azure や ASP.NET、Java EE 系の話題を記載します

今更 Java8 を使ってみる ~その2 インターフェースの default 実装編~

Java 8 からはインターフェースにデフォルトの実装を持てるようになった。Java でデフォルトの実装を持たせる場合、Java 7 までは必ず抽象クラスを経由する必要があったが、Java 8 からは 本機能を利用することで実現が可能になった。

簡単な default 実装の利用方法

default というキーワードを利用して、以下のようにインターフェースに対して標準の実装を持たせることができる。

public interface HelloService{
     defualt String sayHello(String name){
         return name + "さん、こんにちは";
     }
}

もちろんインターフェースは直接インスタンス化できないが、標準的な処理をあらかじめインターフェースに定義することができるため「これだけはこういう実装をして欲しい」という部分をインターフェースに定義可能になったと言える(標準化というものに携わる人にはちょっとうれしい機能な気がする)。

もうちょっと突っ込んでみる

以下のサンプルを実行してみた。

package org.mydomain.defaultinterface;

// インターフェースには暗黙的に final, public, static が付与されるが、
// 今回は明示的に上記の予約語を付与
public interface HelloService {

	// 普通はこんな定義はしないで、あくまで実験用としていただけると
	public static final MyDto dto = new MyDto();

	public String sayGoodBye(String name);

	default public String sayHello(String name) {
		dto.setName(name);
		System.out.println("ここは侵されていないデフォルトメソッド(*´Д`)ハァハァ");
		return name + "さん、卑猥ですね!";
	}
}

class MyDto {
	String name;

	public MyDto() {
		name = "何とも卑猥";
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}
package org.mydomain.defaultinterface;

public class Main {
	public static void main(String[] args) {
		HelloService service = new HelloService() {
			@Override
			public String sayGoodBye(String name) {
				System.out.println("実装してみた系");
				return name + "さん、さようなら(/ω\)イヤン";
			}
		};
		System.out.println("名前 = " + HelloService.dto.getName());
		System.out.println(service.sayHello("卑猥"));
		System.out.println(service.sayGoodBye("淫猥"));
		System.out.println("名前 = " + HelloService.dto.getName());
		System.out.println();

		// もちろんメソッドの上書きも可能
		HelloService service2 = new HelloService() {
			@Override
			public String sayHello(String name) {
				return "もう何もない";
			}

			@Override
			public String sayGoodBye(String name) {
				return null;
			}
		};
		System.out.println(service2.sayHello("aaa"));
	}
}
  • 実行結果
名前 = 何とも卑猥
ここは侵されていないデフォルトメソッド(*´Д`)ハァハァ
卑猥さん、卑猥ですね!
実装してみた系
淫猥さん、さようなら(/ω\)イヤン
名前 = 卑猥

もう何もない

ご覧のとおり、デフォルト実装を定義した場合でも実装クラスにおける処理の上書きは可能であり、インターフェースで状態は持てないことがわかる(final static public なインスタンスは状態が持てるが、これは Java 7 以前からと同様)。

じゃあインターフェースと抽象クラスの区別は?

インターフェースと抽象クラスとの区分けが気になるところだが、以下の言質をいただいておる。