2016-07-12 9 views
1

のJava 7ラムダ式は1つのインターフェイスで動作しますか?

List<Person> personList = Person.createShortList(); 

// Sort with Inner Class 
Collections.sort(personList, new Comparator<Person>() { 
    public int compare(Person p1, Person p2) { 
     return p1.getSurName().compareTo(p2.getSurName()); 
    } 
}); 

のJava 8

Collections.sort(personList, (Person p1, Person p2) -> 
       p1.getSurName().compareTo(p2.getSurName())); 

for (Person p : personList) { 
    p.printName(); 
} 

インタフェースComparatorは2つの方法があり、1つだけでなくcompareそれはラムダを使用することが可能である場合は?例えば

public interface Comparator<T> { 
    int compare(T o1, T o2); 
    int compareTest(T o1, T o2); 
} 
+2

ラムダは、ちょうど1つの抽象メソッドを持つインターフェイスを実装する必要があります。任意の数のデフォルトメソッドを持つことができます。 –

+2

ところで、自分自身の繰り返しを避けるために 'Collections.sort(personList、Comparator.comparing(p - > p.getSurName()));'を使うことができます。 'Collections.sort(PersonList、Comparator.comparing(Person :: getSurName));' – Holger

答えて

4

機能インタフェースの実装が期待されるラムダを使用することができます。機能インターフェースの定義は、JLS§9.8である:

機能インターフェースは(Objectの方法とは別に)ただ1つの抽象メソッドを持つインターフェースであるので、単一の機能契約を表します。この「単一」メソッドは、スーパーインタフェースから継承されたオーバーライド同等のシグネチャを持つ複数の抽象メソッドの形式をとることができます。この場合、継承されたメソッドは論理的に1つのメソッドを表します。

2つの抽象メソッドはComparatorcomparecompareTest)であったのであれば、あなたの例では、ありません、あなたは、ラムダを使用して、それを実装していませんでした。

@FunctionalInterface 
interface Foo { 
    void method1(int x); 
} 

public class Example { 
    public static final void main(String[] args) { 
     new Example().testFoo(x -> { 
      System.out.println(x); 
     }); 
    } 

    private void testFoo(Foo f) { 
     for (int x = 0; x < 5; ++x) { 
      f.method1(x); 
     } 
    } 
} 

...しかし、我々はFooに追加した場合::

例えば、これは動作します

// WON'T COMPILE 
@FunctionalInterface 
interface Foo { 
    void method1(int x); 
    void method2(int x); 
} 

...それはもはや機能インターフェイスだから、それはもうコンパイルしないだろう。 (私たちは、注釈を削除した場合、インターフェイスは[もちろん]コンパイルが、ラムダを経由して、それを私たちの使用しません。)私たちはFooデフォルトメソッドを追加することができます

注:

@FunctionalInterface 
interface Foo { 
    void method1(int x); 
    default void method2(int x) { 
     // ... 
    } 
} 

抽象メソッドがインターフェイスに1つしかないので、これは問題ありません。

+1

正確に言えば、機能的なインタフェースは 'java.langで宣言されたメソッドと一致しない正確に一つの' abstract'メソッドを持たなければなりません.Object'。これは、質問のインターフェース['Comparator'](https://docs.oracle.com/javase/8/docs/api/?java/util/Comparator.html)に2つの' abstract'メソッドがありますが、[そのうちの1つ](https://docs.oracle。com/javase/8/docs/api/java/util/Comparator.html#equals-java.lang.Object-)は、[Object'で宣言されたメソッド]に一致します(https://docs.oracle.com/javase/ 8/docs/api/java/lang/Object.html#equals-java.lang.Object-)。 – Holger

+2

だから 'Comparator'は' static'メソッド、 'default'メソッド、' java.lang.Object'のメソッドにマッチする2番目の 'abstract'メソッドのすべてを持つ機能的インタフェースの良い例です... – Holger

5

ファンクショナルインターフェイスには、インターフェイスには当てはまらない1つの抽象メソッドが必要です。ただし、これらのメソッドのいずれかのデフォルト実装を提供することができます。その場合、それは動作します:

@FunctionalInterface 
public interface Comparator<T> { 

    int compare(T o1, T o2); 

    default int reverseCompare(T o1, T o2) { 
     return compare(o2, o1); 
    } 
} 
+1

Heh、ちょうどデフォルトのメソッドをテストすることから戻ってきました(私は彼らがうまくいくとは思えませんでした)、そして私の答えを更新しました。 :-) –

関連する問題