Java-8仕様を読んでいると、「SAMタイプ」への参照が頻繁に見られます。私はこれが何であるかについての明確な説明を見つけることができませんでした。
SAMタイプとは何ですか?また、使用される場合のシナリオ例は何ですか?
Java-8仕様を読んでいると、「SAMタイプ」への参照が頻繁に見られます。私はこれが何であるかについての明確な説明を見つけることができませんでした。
SAMタイプとは何ですか?また、使用される場合のシナリオ例は何ですか?
回答:
要約するとジョンが投稿リンク1、それが今までダウンした場合のを、「SAM」は「単一抽象メソッド」の略で、「SAM型」のようなインターフェースを指しRunnable
、Callable
ある、などのラムダ式、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トレイルをご覧ください。