インタフェースとは
公開すべき必要な操作をまとめたクラスの仕様のこと。以下にインタフェースの特長をまとめる。
インスタンス化できない
Java(Main.java)
public class Main implements Foo {
public static void main(String[] args) {
Foo foo = new Foo();
}
}
interface Foo{
int num1 = 10;
final int num2 = 20;
}
結果
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
型 Foo のインスタンスを生成できません
at Main.main(Main.java:3)
インタフェースの多重実現が可能
Java(Main.java)
public class Main implements Foo,Foo2 {
public static void main(String[] args) {
System.out.println(Foo.num1);
System.out.println(Foo2.num1);
}
}
interface Foo{
int num1 = 10;
final int num2 = 20;
}
interface Foo2{
int num1 = 20;
final int num2 = 30;
}
結果
10
20
インタフェースの多重継承も可能
Java(Main.java)
public class Main implements Foo,Foo2 {
public static void main(String[] args) {
System.out.println(Foo.num1);
System.out.println(Foo2.num1);
System.out.println(Foo3.num3);
}
}
interface Foo{
int num1 = 10;
final int num2 = 20;
}
interface Foo2{
int num1 = 20;
final int num2 = 30;
}
interface Foo3 extends Foo,Foo2{
int num3 = 50;
}
結果
10
20
50
ただし以下の呼び方をするとエラーになる。
Java(Main.java)
public class Main implements Foo,Foo2 {
public static void main(String[] args) {
System.out.println(Foo.num1);
System.out.println(Foo2.num1);
System.out.println(Foo3.num1);//エラー
}
}
interface Foo{
int num1 = 10;
final int num2 = 20;
}
interface Foo2{
int num1 = 20;
final int num2 = 30;
}
interface Foo3 extends Foo,Foo2{
int num3 = 50;
}
結果
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
フィールド Foo3.num1 はあいまいです
at Main.main(Main.java:5)
インタフェースで定義した変数は自動的にpublic static finalになる
Java(Main.java)
public class Main implements Foo{
public static void main(String[] args) {
Foo.num1 = 20;
}
}
interface Foo{
int num1 = 10;
final int num2 = 20;
}
結果
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
final フィールド Foo.num1 には代入できません
at Main.main(Main.java:3)
インタフェースで定義する変数(インスタンス変数・static変数)のアクセス修飾子はpublicのみ
デフォルトの場合は自動的にpublicに読み替えられる。protectedとprivateはエラー。
Java(Main.java)
interface Foo{
public int num1 = 10;
protected int num2 = 20;//エラー
int num3 = 30;
private num4 = 40;//エラー
}
インタフェースで定義するデフォルトメソッドのアクセス修飾子はpublicのみ
デフォルトの場合は自動的にpublicに読み替えられる。protectedとprivateはエラー。
Java(Main.java)
default public int number1(){
return 10;
}
default protected int number2(){//エラー
return 20;
}
default int number3(){
return 40;
}
default private int number4(){//エラー
return 40;
}
インタフェースで定義するstaticメソッドのアクセス修飾子はpublicとprivateのみ
デフォルトの場合は自動的にpublicに読み替えられる。protectedはエラー。
Java(Main.java)
public static int number1() {
return 10;
}
protected static int number2() {//エラー
return 20;
}
static int number3() {
return 30;
}
private static int number4() {
return 40;
}
インタフェースに定めたメソッドは実現しないといけない
Java(Main.java)
public class Main {
public static void main(String[] args) {
Add add = new Add();
System.out.println(add.calc(2,7));
}
}
interface Foo{
public int calc(int a,int b);
}
//Fooの継承
//Calcメソッド実装
class Add implements Foo{
public int calc(int a,int b) {
return a + b;
}
}
結果
9
デフォルトメソッドでjava.lang.Objectのメソッドをオーバーライドできない
Java(Main.java)
interface Foo{
default String toString() { //エラー
return "aaa";
}
}
元のデフォルトメソッドを呼び出す場合、インタフェース名.super.メソッド名で呼び出す
Java(Main.java)
public class Main {
public static void main(String[] args) {
Add add = new Add();
System.out.println(add.calc(2,7));
System.out.println(add.callSuperNum(2,7));
}
}
interface Foo{
default int num(int a,int b) {
return a * b;
}
}
//Fooの継承
//Calcメソッド実装
class Add implements Foo{
public int calc(int a,int b) {
return a + b;
}
public int callSuperNum(int a,int b) {
return Foo.super.num(a, b);
}
}
結果
9
14
共変戻り値について
これはインタフェースを実装したメソッド、またはサブクラスでオーバーライドするメソッドの戻り値が、その戻り値のサブクラスでも良いという仕様。
Java(A.java)
public interface A{
public Iterable a();
}
Java(B.java)
import java.util.Collection;
public interface B extends A{
public Collection a();
}
Java(C.java)
import java.nio.file.Path;
public interface C extends A{
public Path a();
}
BインタフェースとCインタフェースでaメソッドを実装しているが、AインタフェースのIterable型で戻していない。IterableインタフェースはCollectionやPathのスーパーインタフェースなので、問題無く動く。
まとめ
- インスタンス化できない
- インタフェースの多重実現が可能
- インタフェースの多重継承も可能
- インタフェースで定義した変数は自動的にpublic static finalになる
- インタフェースで定義する変数(インスタンス変数・static変数)のアクセス修飾子はpublicのみ
- インタフェースで定義するデフォルトメソッドのアクセス修飾子はpublicのみ
- インタフェースで定義するstaticメソッドのアクセス修飾子はpublicとprivateのみ
- インタフェースに定めたメソッドは実現しないといけない
- デフォルトメソッドでjava.lang.Objectのメソッドをオーバーライドできない
- 元のデフォルトメソッドを呼び出す場合、インタフェース名.super.メソッド名で呼び出す
- 共変戻り値とはインタフェースを実装したメソッド、またはサブクラスでオーバーライドするメソッドの戻り値が、その戻り値のサブクラスでも良いという仕様