일부 익명 내부 클래스 교체 이 섹션에서는 익명 내부 클래스 작성을 단순화하기 위해 Lambda 표현식을 사용하는 방법을 소개합니다. 그러나 Lambda 표현식은 모든 익명 내부 클래스를 대체하는 데만 사용할 수 있습니다. 아직 세부사항에 대해 걱정하지 마세요. 몇 가지 예를 살펴보겠습니다.
예 1: 매개변수 없는 함수의 약어 새 스레드를 생성해야 하는 경우 일반적인 작성 방법은 다음과 같습니다.
// JDK7 익명 내부 클래스 작성 방법 new Thread(new Runnable(){// 인터페이스 이름
으아악
}).start(); 위 코드는 익명의 Runnable 객체를 Tread 클래스에 전달하고 Runnable 인터페이스의 run() 메서드를 오버로드하여 해당 로직을 구현합니다. 이는 JDK7 및 이전 버전에서 일반적인 작성 방법입니다. 익명 내부 클래스를 사용하면 클래스 이름을 지정하는 수고를 덜 수 있지만 Java 8에서는 다음 형식으로 단순화할 수 있습니다.
// JDK8 Lambda 표현식 작성 방법
새 스레드(
으아악
).start();
위 코드는 익명 내부 클래스와 기능은 동일하지만 익명 내부 클래스보다 더 많은 기능을 수행합니다. 여기서는 연결 포트명과 함수명을 함께 생략하여 작성하기가 더 산뜻해졌습니다. 함수 본문에 여러 줄이 있는 경우 다음과 같이 중괄호로 묶을 수 있습니다.
// JDK8 Lambda 표현식 코드 블록 작성 방법
new Thread(
으아악
).start();
예제 2: 매개변수가 있는 함수의 약어 사용자 정의 비교기를 문자열 목록에 전달하고 문자열 길이에 따라 정렬하려는 경우 Java 7의 작성 형식은 다음과 같습니다.
// JDK7에서 익명 내부 클래스를 작성하는 방법
List<String> list = Arrays.asList("I", "love", "you", "too"); Collections.sort(list, new Comparator<String> ;() {//인터페이스 이름
으아악
});
위 코드는 비교 논리를 구현하기 위해 내부 클래스를 통해 Comparator 인터페이스의 Compare() 메서드를 오버로드합니다. 람다 표현식을 사용하는 것은 다음과 같이 축약될 수 있습니다:
위 코드는 익명 내부 클래스와 동일한 기능을 가지고 있습니다. 인터페이스 이름과 메소드 이름을 생략하는 것 외에도 코드에서는 매개변수 테이블의 유형도 생략합니다. 이는 javac의 유형 추론 메커니즘 때문입니다. 물론, 추론이 실패하는 경우도 있습니다. 이 경우 매개변수 유형을 수동으로 지정해야 합니다. Java는 강력한 형식의 언어이므로 각 변수와 개체에는 명확한 형식이 있어야 합니다.
약어의 기본
아마도 Lambda를 사용하는 기본은 해당하는 기능적 인터페이스가 있어야 한다는 것이라고 이미 생각했을 것입니다(기능적 인터페이스는 내부에 단 하나의 추상 메서드만 있는 인터페이스를 나타냄). 이는 Java가 강력한 유형의 언어라는 점과 일치합니다. 즉, 코드의 어느 위치에서나 Lambda 표현식을 임의로 작성할 수 없다는 의미입니다. 실제로 Lambda의 유형은 함수 인터페이스에 해당하는 유형입니다. 람다 식의 또 다른 기반은 형식 유추 메커니즘입니다. 컨텍스트 정보가 충분하면 컴파일러는 명시적으로 이름을 지정하지 않고도 매개 변수 테이블의 형식을 유추할 수 있습니다. Lambda는 다음과 같이 더 많은 법적 서면 형식을 표현합니다.
// 람다 표현식의 작성된 형태 Runnable run = () -> System.out.println("Hello World");// 1 ActionListener 리스너 = event -> );// 2 실행 가능한 multiLine = () -> {// 3개 코드 블록
으아악
}; BinaryOperator<Long> add = (Long x, Long y) -> x + y;// 4 BinaryOperator<Long> addImplicit = (x, y) -> 2는 매개변수화된 함수의 약어를 보여주고, 3은 코드 블록의 작성 방법을 보여줍니다.
사용자 정의 함수 인터페이스
사용자 정의 함수 인터페이스는 쉽습니다. 하나의 추상 메서드만 사용하여 인터페이스를 작성하면 됩니다.
// 사용자 정의 함수 인터페이스
@FunctionalInterface 공개 인터페이스 ConsumerInterface<T>{
으아악
위 코드의
}
@FunctionalInterface는 선택 사항이지만 이 주석을 추가하면 컴파일러가 인터페이스가 기능적 인터페이스 사양을 준수하는지 확인하는 데 도움이 됩니다. @Override 주석을 추가하는 것과 마찬가지로 함수가 오버로드되었는지 확인합니다.
위의 인터페이스 정의를 사용하면 다음과 유사한 코드를 작성할 수 있습니다.
ConsumerInterface<String> 소비자 = str -> System.out.println(str);
또한 다음과 같이 사용할 수도 있습니다.
class MyStream<T>{
으아악
}
MyStream<String> stream = new MyStream<String>(); stream.myForEach(str -> System.out.println(str));// 사용자 정의 함수 인터페이스를 사용하여 Lambda 표현식 작성
일부 익명 내부 클래스 교체
이 섹션에서는 익명 내부 클래스 작성을 단순화하기 위해 Lambda 표현식을 사용하는 방법을 소개합니다. 그러나 Lambda 표현식은 모든 익명 내부 클래스를 대체하는 데만 사용할 수 있습니다. 아직 세부사항에 대해 걱정하지 마세요. 몇 가지 예를 살펴보겠습니다.
예 1: 매개변수 없는 함수의 약어
새 스레드를 생성해야 하는 경우 일반적인 작성 방법은 다음과 같습니다.
// JDK7 익명 내부 클래스 작성 방법
으아악new Thread(new Runnable(){// 인터페이스 이름
}).start();
// JDK8 Lambda 표현식 작성 방법위 코드는 익명의 Runnable 객체를 Tread 클래스에 전달하고 Runnable 인터페이스의 run() 메서드를 오버로드하여 해당 로직을 구현합니다. 이는 JDK7 및 이전 버전에서 일반적인 작성 방법입니다. 익명 내부 클래스를 사용하면 클래스 이름을 지정하는 수고를 덜 수 있지만 Java 8에서는 다음 형식으로 단순화할 수 있습니다.
새 스레드(
).start();으아악
위 코드는 익명 내부 클래스와 기능은 동일하지만 익명 내부 클래스보다 더 많은 기능을 수행합니다. 여기서는 연결 포트명과 함수명을 함께 생략하여 작성하기가 더 산뜻해졌습니다. 함수 본문에 여러 줄이 있는 경우 다음과 같이 중괄호로 묶을 수 있습니다.
// JDK8 Lambda 표현식 코드 블록 작성 방법new Thread(
).start();으아악
예제 2: 매개변수가 있는 함수의 약어
// JDK7에서 익명 내부 클래스를 작성하는 방법사용자 정의 비교기를 문자열 목록에 전달하고 문자열 길이에 따라 정렬하려는 경우 Java 7의 작성 형식은 다음과 같습니다.
List<String> list = Arrays.asList("I", "love", "you", "too");
});Collections.sort(list, new Comparator<String> ;() {//인터페이스 이름
으아악
위 코드는 비교 논리를 구현하기 위해 내부 클래스를 통해 Comparator 인터페이스의 Compare() 메서드를 오버로드합니다. 람다 표현식을 사용하는 것은 다음과 같이 축약될 수 있습니다:
// JDK8 람다 표현식 작성 방법List<String> list = Arrays.asList("I", "love", "you", "too");
});Collections.sort(list, (s1, s2) - > ;{// 매개변수 테이블 유형 생략
으아악
위 코드는 익명 내부 클래스와 동일한 기능을 가지고 있습니다. 인터페이스 이름과 메소드 이름을 생략하는 것 외에도 코드에서는 매개변수 테이블의 유형도 생략합니다. 이는 javac의 유형 추론 메커니즘 때문입니다. 물론, 추론이 실패하는 경우도 있습니다. 이 경우 매개변수 유형을 수동으로 지정해야 합니다. Java는 강력한 형식의 언어이므로 각 변수와 개체에는 명확한 형식이 있어야 합니다.
약어의 기본아마도 Lambda를 사용하는 기본은 해당하는 기능적 인터페이스가 있어야 한다는 것이라고 이미 생각했을 것입니다(기능적 인터페이스는 내부에 단 하나의 추상 메서드만 있는 인터페이스를 나타냄). 이는 Java가 강력한 유형의 언어라는 점과 일치합니다. 즉, 코드의 어느 위치에서나 Lambda 표현식을 임의로 작성할 수 없다는 의미입니다. 실제로 Lambda의 유형은 함수 인터페이스에 해당하는 유형입니다. 람다 식의 또 다른 기반은 형식 유추 메커니즘입니다. 컨텍스트 정보가 충분하면 컴파일러는 명시적으로 이름을 지정하지 않고도 매개 변수 테이블의 형식을 유추할 수 있습니다. Lambda는 다음과 같이 더 많은 법적 서면 형식을 표현합니다.
// 람다 표현식의 작성된 형태
으아악Runnable run = () -> System.out.println("Hello World");// 1
ActionListener 리스너 = event -> );// 2
실행 가능한 multiLine = () -> {// 3개 코드 블록
};
사용자 정의 함수 인터페이스BinaryOperator<Long> add = (Long x, Long y) -> x + y;// 4
BinaryOperator<Long> addImplicit = (x, y) -> 2는 매개변수화된 함수의 약어를 보여주고, 3은 코드 블록의 작성 방법을 보여줍니다.
사용자 정의 함수 인터페이스는 쉽습니다. 하나의 추상 메서드만 사용하여 인터페이스를 작성하면 됩니다.
// 사용자 정의 함수 인터페이스@FunctionalInterface
}공개 인터페이스 ConsumerInterface<T>{
으아악 위 코드의
@FunctionalInterface는 선택 사항이지만 이 주석을 추가하면 컴파일러가 인터페이스가 기능적 인터페이스 사양을 준수하는지 확인하는 데 도움이 됩니다. @Override 주석을 추가하는 것과 마찬가지로 함수가 오버로드되었는지 확인합니다.
위의 인터페이스 정의를 사용하면 다음과 유사한 코드를 작성할 수 있습니다.으아악
}MyStream<String> stream = new MyStream<String>();
stream.myForEach(str -> System.out.println(str));// 사용자 정의 함수 인터페이스를 사용하여 Lambda 표현식 작성
할 수 없는 것은 Lambda 자체가 객체가 아니라는 것입니다.