Java에서 'SAM 유형'이란 무엇입니까?


133

Java-8 사양을 읽으면서 'SAM 유형'에 대한 참조가 계속 표시됩니다. 이것이 무엇인지에 대한 명확한 설명을 찾을 수 없었습니다.

SAM 유형이란 무엇이며 언제 사용되는지에 대한 시나리오 예는 무엇입니까?


4
참조 cr.openjdk.java.net/~briangoetz/lambda/lambda-state-3.html (I 다른 SO 질문에 나를 데려 하나의 검색 후 발견).
Jon Skeet

2
사람들에게 오래된 정보를 알려주지 마십시오. 약간 더 길게 검색하면 최신 버전 인 cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.html로 이동했을 것입니다. 장소. OP의 질문은 lambdafaq.org/what-is-a-functional-interface 에서 FAQ의 한 페이지로 최근에 빠르게 변화하는 언어 및 API 개발에 대한 최신 정보를 유지하려고합니다.
Maurice Naftalin

1
@MauriceNaftalin 개발팀이 최신으로 유지하고 있는 Java 트레일을 링크 할 수도 있습니다 .
Brian

1
현재 용어는 "기능적 인터페이스"입니다.
newacct

1
@MauriceNaftalin : 미안합니다. 내가 찾았다면 분명히 그것에 연결되었을 것입니다.
Jon Skeet 5

답변:


142

요약 존 게시 링크 1 은 지금까지 다운 될 경우를, "SAM"은 "하나의 추상 메소드"를 의미하고, "SAM-type은"와 같은 인터페이스를 의미 Runnable, Callable있다, 등 람다 표현식, 자바 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에 추가 된 바이트 코드 명령어를 사용하여 이러한 기능을 구현합니다 . 앞에서 Lambda를 선언 하면 익명 클래스 의 인스턴스를 만들 Callable거나 Comparable유사한 클래스를 만들지 만 엄격하게 사실 은 아닙니다 . 대신,를 처음 invokedynamic호출하면 LambdaMetafactory.metafactory메소드 를 사용 하여 Lambda 함수 핸들러를 생성 한 다음 이후에 Lambda를 호출 할 때이 캐시 된 인스턴스를 사용합니다. 자세한 내용은 이 답변 에서 확인할 수 있습니다 .

이 접근 방식은 복잡하며 스택 메모리에서 직접 기본 값과 참조를 읽어 Lambda 코드로 전달할 수있는 코드를 포함합니다 (예 : Object[]Lambda를 호출하기 위해 배열을 할당해야하는 경우 ). 그러나 향후 Lambda 구현을 반복 할 수 있습니다. 바이트 코드 호환성에 대해 걱정할 필요없이 이전 구현을 대체합니다. Oracle의 엔지니어가 최신 버전의 JVM에서 기본 Lambda 구현을 변경하는 경우 이전 JVM에서 컴파일 된 Lambdas는 개발자의 변경없이 자동으로 최신 구현을 사용합니다.


1 링크의 구문이 오래되었습니다. 상기 살펴보세요 람다 표현식 자바 트레일을 현재의 구문을 확인합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.