Javaの「SAMタイプ」とは何ですか?


133

Java-8仕様を読んでいると、「SAMタイプ」への参照が頻繁に見られます。私はこれが何であるかについての明確な説明を見つけることができませんでした。

SAMタイプとは何ですか?また、使用される場合のシナリオ例は何ですか?


4
cr.openjdk.java.net/~briangoetz/lambda/lambda-state-3.htmlを参照してください(1回の検索で見つかったため、別のSOの質問に移動しました)。
Jon Skeet、2013

2
古くなった情報を紹介しないでください。少し長く検索すると、最新バージョンcr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.htmlに移動します。このバージョン自体は18か月前のものであり、現在多くのバージョンで古くなっています場所。OPの質問はlambdafaq.org/what-is-a-functional-interfaceで回答されています。FAQの 1つのページで、最近まで急速に変化している言語とAPI開発について最新情報を入手しようとしています。
モーリスナフタリン2013

1
@MauriceNaftalinまた、開発チームによって最新に保たれているJavaトレイルをリンクすることもできます。
ブライアン

1
現在の用語は「機能インターフェース」です。
newacct 2013

1
@MauriceNaftalin:すみません、見逃しました。私がそれを見つけたなら、確かにそれにリンクしたでしょう。
Jon Skeet、2013

回答:


142

要約するとジョンが投稿リンク1、それが今までダウンした場合のを、「SAM」は「単一抽象メソッド」の略で、「SAM型」のようなインターフェースを指しRunnableCallableある、などのラムダ式、Javaの8の新機能で、 SAMタイプと見なされ、自由に変換できます。

たとえば、次のようなインターフェースの場合:

public interface Callable<T> {
    public T call();
}

次のCallableようなラムダ式を使用して宣言できます。

Callable<String> strCallable = () -> "Hello world!";
System.out.println(strCallable.call()); // prints "Hello world!"

このコンテキストでのラムダ式は、ほとんどが構文糖衣です。匿名クラスよりもコードの方が見栄えがよく、メソッドの命名に制限がありません。リンクからこの例を見てみましょう:

class Person { 
    private final String name;
    private final int age;

    public static int compareByAge(Person a, Person b) { ... }

    public static int compareByName(Person a, Person b) { ... }
}

Person[] people = ...
Arrays.sort(people, Person::compareByAge);

これは、Comparatorと同じ名前を共有しない特定のメソッドを使用してを作成します。これにより、メソッドComparator.compareのインターフェイスの命名に従う必要がなく、クラスで複数の比較オーバーライドを行うことができ、コンパレータをオンザフライで作成できますラムダ式。

より深く行く...

より深いレベルでは、Java invokedynamicはJava 7で追加されたバイトコード命令を使用してこれらを実装します。前に、ラムダを宣言すると匿名クラスのインスタンスCallableまたはComparable類似のインスタンスが作成されると述べましたが、厳密には正しくありません。代わりに、が初めてinvokedynamic呼び出されたときに、LambdaMetafactory.metafactoryメソッドを使用してLambda関数ハンドラーを作成し、その後、Lambdaの今後の呼び出しでこのキャッシュされたインスタンスを使用します。詳細については、この回答をご覧ください。

このアプローチは複雑で、プリミティブ値と参照をスタックメモリから直接読み取ってLambdaコードに渡すことができるコード(たとえばObject[]、Lambdaを呼び出すために配列を割り当てる必要を回避するため)も含まれますが、Lambda実装の将来の反復が可能ですバイトコードの互換性を気にすることなく、古い実装を置き換える。Oracleのエンジニアが新しいバージョンのJVMで基礎となるLambda実装を変更した場合、古いJVMでコンパイルされたLambdaは、開発者側で変更を加えることなく、新しい実装を自動的に使用します。


1リンクの構文が古くなっています。現在の構文を確認するには、ラムダ式のJavaトレイルをご覧ください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.